以这种方式运行两个计时器是可以实现的。就个人而言,我会编写一个“信号”类,用它自己的时间和绘画例程控制单个灯光,但这不是你所要求的。
您需要做的是为每个信号维护某种状态变量并分别更新它们。
然后,您需要修改绘制代码以检测这些状态并采取适当的措施......例如
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestBlink {
public static void main(String[] args) {
new TestBlink();
}
public TestBlink() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Timer blink1;
private Timer blink2;
private boolean light1 = false;
private boolean light2 = false;
public TestPane() {
blink1 = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
light1 = !light1;
repaint();
}
});
blink2 = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
light2 = !light2;
repaint();
}
});
blink1.start();
blink2.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int radius = 20;
int x = (getWidth() - (radius * 2)) / 2;
int y = (getHeight() - (radius * 2)) / 2;
Ellipse2D signal1 = new Ellipse2D.Float(x, y, radius, radius);
Ellipse2D signal2 = new Ellipse2D.Float(x + radius, y, radius, radius);
g2d.setColor(Color.RED);
g2d.draw(signal1);
if (light1) {
g2d.fill(signal1);
}
g2d.setColor(Color.GREEN);
g2d.draw(signal2);
if (light2) {
g2d.fill(signal2);
}
g2d.dispose();
}
}
}
更新
更好的解决方案(正如我之前所说的)是在单个类中包含单个序列的所有逻辑。这样可以隔离绘画并允许您更改每个序列的个人性质。
例如...
这是一个使用固定变化率的简单示例,因此每盏灯的时间都相同......
public class TraficLight01 extends JPanel {
public static final int RADIUS = 20;
private Timer timer;
private int state = 0;
public TraficLight01() {
timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
state++;
if (state > 2) {
state = 0;
}
repaint();
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(RADIUS, (RADIUS + 1) * 3);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int radius = 20;
Ellipse2D light = new Ellipse2D.Float(0, 0, RADIUS, RADIUS);
int x = (getWidth() - radius) / 2;
int y = ((getHeight()- (radius * 3)) / 2) + (radius * 2);
Color color[] = new Color[]{Color.RED, Color.YELLOW, Color.GREEN};
for (int index = 0; index < color.length; index++) {
g2d.translate(x, y);
g2d.setColor(color[index]);
g2d.draw(light);
if (state == index) {
g2d.fill(light);
}
g2d.translate(-x, -y);
y -= radius + 1;
}
g2d.dispose();
}
}
或者你为每盏灯提供一个可变的间隔......
public static class TraficLight02 extends JPanel {
public static final int RADIUS = 20;
private Timer timer;
private int state = 0;
// Green, Yellow, Red
private int[] intervals = new int[]{3000, 500, 3000};
public TraficLight02() {
timer = new Timer(intervals[0], new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
timer.stop();
state++;
if (state > 2) {
state = 0;
}
timer.setInitialDelay(intervals[state]);
repaint();
timer.restart();
}
});
timer.start();
timer.setRepeats(false);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(RADIUS, (RADIUS + 1) * 3);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int radius = 20;
Ellipse2D light = new Ellipse2D.Float(0, 0, RADIUS, RADIUS);
int x = (getWidth() - radius) / 2;
int y = ((getHeight()- (radius * 3)) / 2) + (radius * 2);
Color color[] = new Color[]{Color.GREEN, Color.YELLOW, Color.RED};
for (int index = 0; index < color.length; index++) {
g2d.translate(x, y);
g2d.setColor(color[index]);
g2d.draw(light);
if (state == index) {
g2d.fill(light);
}
g2d.translate(-x, -y);
y -= radius + 1;
}
g2d.dispose();
}
}
改变这两个概念以通过一种setter
方法以可变间隔播种它们并不需要太多。
同样,您可以使用三个Timer
s,每次触发一个,您只需启动下一个。通过这种方式,您可以定义一系列计时器,每个计时器在其父级完成后以不同的间隔触发......