我有(应该是)一个简单的问题需要解决,我对其他解决方法持开放态度。我对其他解决方案持开放态度。
问题: 我们使用java swing来显示基于回合的,基于图块的游戏的图形。我正在使用带有图标的jlabels,绝对定位。
要为动作制作动画,我使用的是一个摆动计时器,每次更新4个像素的位置,慢慢向右,向左移动精灵等。
为了实现这一目标,我正在运行一个计时器,它运行得非常好。当我试图向下移动然后向右移动时,问题出现了。
精灵向下移动,从不向右移动,如果我通过某些控制台打印观察执行,很明显两个计时器同时运行。我已经在互联网上做了相当多的挖掘工作,直到第一个计时器停止,我才能找到一种告诉摆动计时器不执行的方法,如果我试着忙 - 等到一个计时器完成(根本没有显示UI(显然是向错误方向迈出的一步)。
现在我可以完全转离计时器,或者将精灵传送到新的位置,或使用一些可怕的忙等待运动方案,但我希望某种灵魂有解决方案。
简而言之:我需要一种方法在一段时间内运行一个摆动计时器,停止它,然后然后启动一个新计时器,这样它们就不会重叠。优选地,该方法将允许每个计时器处于其自己的方法中,然后我可以一个接一个地调用这些方法。
提前感谢你提出的任何建议。
编辑:扩展示例代码。如果完整的scsse是你的建议的要求,那么我很抱歉浪费你的时间,因为完整的代码是一个野兽。这个示例代码根本不起作用,抱歉,但它应该说明这一点。
因此。我们有两个函数,每个函数都有一个运行动画循环的计时器,一个用于向下和向右对角移动,一个用于直接向下移动。
public class TestClass {
static int counter = 0;
static int counter2 = 0;
static Timer timerC;
static Timer timerX;
public static void main(String[] args) {
moveC();
moveX();
}
public static void moveC() {
int delay = 200; // milliseconds
timerC = new Timer(delay, null);
timerC.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (counter < 32) {
counter = counter + 4;
System.out.println("*C*");
} else {
timerC.stop();
System.out.println("*C STOP*");
}
}
});
timerC.start();
}
public static void moveX() {
int delay = 200; // milliseconds
timerX = new Timer(delay, null);
timerX.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (counter < 32) {
counter = counter + 4;
System.out.println("*X*");
} else {
timerX.stop();
System.out.println("*X STOP*");
}
}
});
timerX.start();
}
}
我最终希望看到的是
*C*
*C*
*C*
*C*
*C STOP*
*X*
*X*
*X*
*X*
*X STOP*
我实际得到的是
*C*
*X*
*C*
*X*
*C*
*X*
*C*
*X*
*C STOP*
*X STOP*
我试图在这里得到的一点是运行一个动画周期,然后是另一个。
再次感谢。
答案 0 :(得分:5)
不要使用多个计时器,而是只使用一个计时器来处理每个方向。您需要某种类型的队列来保存方向信息,无论是正式队列还是用作队列的集合(先进先出),然后让Timer在运行时从该队列中提取方向。例如,在这里我使用我的JList模型作为我的队列,删除并使用首先添加的Direction(在JList的顶部):
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
public class TimerPlay extends JPanel {
private DefaultListModel directionJListModel = new DefaultListModel();
private JList directionJList = new JList(directionJListModel);
JButton startTimerButton = new JButton(
new StartTimerBtnAction("Start Timer"));
public TimerPlay() {
ActionListener directionBtnListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent actEvt) {
String actionCommand = actEvt.getActionCommand();
Direction dir = Direction.valueOf(actionCommand);
if (dir != null) {
directionJListModel.addElement(dir);
}
}
};
JPanel directionBtnPanel = new JPanel(new GridLayout(0, 1, 0, 10));
for (Direction dir : Direction.values()) {
JButton dirBtn = new JButton(dir.toString());
dirBtn.addActionListener(directionBtnListener);
directionBtnPanel.add(dirBtn);
}
add(directionBtnPanel);
add(new JScrollPane(directionJList));
add(startTimerButton);
}
private class StartTimerBtnAction extends AbstractAction {
protected static final int MAX_COUNT = 20;
public StartTimerBtnAction(String title) {
super(title);
}
@Override
public void actionPerformed(ActionEvent arg0) {
startTimerButton.setEnabled(false);
int delay = 100;
new Timer(delay, new ActionListener() {
private int count = 0;
private Direction dir = null;
@Override
public void actionPerformed(ActionEvent e) {
if (count == MAX_COUNT) {
count = 0; // restart
return;
} else if (count == 0) {
if (directionJListModel.size() == 0) {
((Timer)e.getSource()).stop();
startTimerButton.setEnabled(true);
return;
}
// extract from "queue"
dir = (Direction) directionJListModel.remove(0);
}
System.out.println(dir); // do movement here
count++;
}
}).start();
}
}
private static void createAndShowGui() {
TimerPlay mainPanel = new TimerPlay();
JFrame frame = new JFrame("TimerPlay");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
enum Direction {
UP, DOWN, LEFT, RIGHT;
}
答案 1 :(得分:4)
答案 2 :(得分:4)
将所有Icon
放入某种形式的数组
创建一个具有短暂延迟的单个Swing Timer
在Swing ActionListener
中,从数组中取出每个`图标,从屏幕获取getBounds,将Icon移动一步
重复直到达到目标。