我正在使用 Swing Timer 在我的程序中执行动画。在许多情况下,会同时对 animate() 方法进行多个不同的调用,并为每个调用创建一个单独的计时器。我知道,由于 Swing 计时器的设计方式,这些都一起执行 - 我的所有动画同时发生。但是,在某些情况下,我需要等待一个动画完成才能执行另一个动画。
有没有一种方法可以让 Swing 计时器按顺序执行 - 一个接一个,而不是一次全部执行?或者是否有 Swing 计时器的替代机制可能更适合我的用例?
编辑:恐怕我有点过于简化了我的用例。如果我知道在每个“场景转换”需要执行哪些动画,或者每次都发生相同的动画序列,@peeskillet 的建议将非常有效。不幸的是,情况并非如此——每个转换都需要一组不同的动画,不同组的组件在面板上移入、移出和移动。
我想要的是首先执行屏幕外项目的动画,然后(完成后)为屏幕上的组件设置动画。在运行时区分这些动画“类型”不是问题 - 它们是从不同的方法启动的,因此很容易想象将它们添加到两个不同的“队列” - 传出项目队列和传入项目队列。完成此操作后,我就可以实现调用
的基本策略也就是说 - 这一切对我来说只有直观地、启发式地才有意义 - 我还没有弄清楚如何在实践中实现它。这些“队列”实际上是什么,什么类将保存并稍后执行它们?大概是实现 Runnable 的线程,创建第二个线程来执行动画并更严格地控制动画的进行方式?或者,如果我完全掌握如何使用事件分派(dispatch)线程,它是否可以为我提供足够的控制权?在这种情况下 - 请帮我做到这一点。
(PS我意识到我在这里显着改变了这个问题,本质上把它变成了一个新问题,并且@peetskillet按照之前的措辞很好地回答了它,所以我接受了这个答案并发布了一个新问题here.
最佳答案
"Is there a way to make Swing timers execute sequentially - one after the other, rather than all at once? "
只需使用某种“boolean 值”,告诉第一个计时器何时应停止以及第二个计时器何时应启动。类似的东西
Timer timer1 = new Timer(delay, null); <---- initialize
Timer timer2 = new Timer(delay, null);
boolean something = false;
public Constructor() {
timer1 = new Timer(delay, new Action Listener(){
public void actionPerformed(ActionEvent e) {
if (something) { ------
timer2.start(); |
timer1.stop(); |---- some code should lead to
} esle { | `something` being true. Maybe
animateFirstSomething(); | another if statement inside the
} | else. Like if x equals y
} ------ something = true, else,
}); animateFirstSomething()
timer1.start();
timer2 = new Timer(delay, new ActionListener(){
public void actionPerformed(ActionEvent e) {
animationSecondSomething();
}
});
}
<小时/>
这是一个简单的例子
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class TestTwoTimers extends JPanel {
int rectOneX = 0;
int rectTwoX = 0;
Timer timer1 = new Timer(100, null);
Timer timer2 = new Timer(100, null);
boolean rectOneGo = true;
public TestTwoTimers() {
timer1 = new Timer(100, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (rectOneGo) {
if (rectOneX >= 225) {
timer2.start();
timer1.stop();
} else {
rectOneX += 10;
repaint();
}
}
}
});
timer2 = new Timer(100, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (rectTwoX < 225) {
rectTwoX += 10;
repaint();
} else {
timer2.stop();
}
}
});
final JButton button = new JButton("Start First Timer");
button.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
timer1.start();
}
});
setLayout(new BorderLayout());
add(button, BorderLayout.PAGE_END);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(rectOneX, 50, 75, 75);
g.setColor(Color.BLUE);
g.fillRect(rectTwoX, 150, 75, 75);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
JFrame frame = new JFrame("Double Timers");
frame.add(new TestTwoTimers());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
关于java - 顺序 Swing 定时器执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21298002/