我正在尝试创建一个Asteroids游戏,但一开始我就很努力:我想在游戏开始之前创建一个倒数计时。为此,我使用了一个计时器,该计时器在按下“启动”按钮时启动,并且(应该)每秒加载一个BufferedImage
,然后将其显示在JFrame
上。
在添加计时器之前,整个过程运行良好。但是,图像仍在绘制中,run()
的方法TimerTask
仍在使用中。但是,该图像没有出现在我的JFrame
上。
public class Main implements ActionListener {
private static File load = null;
private static BufferedImage image = null;
private JFrame frame;
private JButton start;
private JLabel game_name;
private JLabel screen;
private ImageIcon icon;
private Asteroids aster = new Asteroids();
private static Main m = new Main();
protected static int height = 550;
protected static int width = 800;
protected static int cd = 0;
/*
* Here the JFrame frame gets created and set up, and the main method
* does its job. I believe only the actionPerformed method to be
* important, so I removed this part from the post.
*
*/
private void addScreen() {
frame.add(screen);
}
@Override
public void actionPerformed(ActionEvent ae) {
// Cleaning the screen
start.setVisible(false);
game_name.setVisible(false);
// Creating the image
aster.spawn(5);
// creating the countdown timer
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
// creating countdown
aster.initialScreen();
// Reading the image
load = new File(aster.filePath + aster.fileName + ".png");
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
try {
image = ImageIO.read(load);
} catch (IOException i) {
System.out.println("Reading has encountered an error: \n" + i); }
// Implementing the Image
screen = new JLabel();
screen.setSize(width, height);
icon = new ImageIcon(image);
screen.setIcon(icon);
m.addScreen();
System.out.println("roger");
}
}, 0, 1000);
} // end actionPerfomed()
} // end class
有人可以发现错误吗?我真的不明白问题是什么,虽然我是定时器的新手,所以如果我做的真的很愚蠢,请告诉我。
答案 0 :(得分:1)
您的问题很可能是因为您正在使用java.util.Timer
,它会启动其自己的后台线程并在访问Swing组件时导致并发问题。
无论如何,我建议使用javax.swing.Timer
,它将您的任务安排为要在Swing事件分配线程上执行的动作侦听器:
new javax.swing.Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Your code here
}
}).start();
答案 1 :(得分:0)
好的,所以我以某种方式解决了这个问题:
首先,我确实将util.Timer更改为swing.Timer,但这本身并没有帮助。
以前,在将每个图像绘制到桌面上之后,我要保存它们,然后将其加载到屏幕上以显示它。我花了一些时间处理代码,发现不需要保存它,但实际上可以通过将其设置为static
来直接引用它。当我这样做时,问题就消失了。这是我的意思的代码示例:
之前:
// In the drawing class
save = new File(aster.filePath + aster.fileName + ".png");
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
try {
ImageIO.write(image, "png", save);
} catch (IOException i) {
System.out.println("Writing has encountered an error: \n" + i); }
// In the displaying class
load = new File(aster.filePath + aster.fileName + ".png");
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
try {
image = ImageIO.read(load);
} catch (IOException i) {
System.out.println("Reading has encountered an error: \n" + i); }
ImageIcon icon = new ImageIcon(image);
displayingJLabel.setIcon(icon);
frame.add(displayingJLabel);
之后:
// One static declaration and initialization of an BufferedImage in the drawing class
public static BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// Drawing Code
// Accessing the image
ImageIcon icon = new ImageIcon(DrawingClass.image);
displayingJLabel.setIcon(icon);
frame.add(displayingJLabel);
从本质上讲,所有内容都是相同的,只是跳过了整个保存和读取过程,而我只使用一个BufferedImage
而不是几个本地static BufferedImage
。
我不确定为什么会这样,但是我的猜测是,整个读取和写入过程花费的时间太长,以致于Timer每秒无法启动,而且这种新方法要快得多。我没有尝试再次使用util.Timer来完成整个操作,但是我认为swing.Timer在解决此问题方面可能有其应有的份额。