我有:
我希望,在JButton的新闻界推出一个新的JFrame,显示Canvas子类,因为它动画。
我现在面临的问题是新的JFrame出现了,但它没有机会渲染任何东西,主框架上的JButton仍然处于低位状态。我认为这背后的逻辑是,EDT还没有完成它的工作,例如将JButton显示为已释放,因此没有机会运行动画方法并最终陷入僵局。
这个逻辑过去对我很好,因为我通过创建一个新线程来完成这项工作,但是最近我学到了更多关于Java,线程和Swing的知识,我已经知道所有Swing相关的事件必须在一个线程上处理:美国东部时间。
这让我感到困惑,因为我之前如何使它工作,但让我相信使用invokeLater可以帮助解决问题;因为让JFrame可见并且显示动画的工作将被放置在队列的末尾,允许JButton取消等等。但是我没有运气;我完全误解了什么吗?
谢谢!
(也请不要评论我使用Canvas类而不是JPanel,我有我的理由。)
示例代码:
Test5 (使用main方法的类)。
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*
public class Test5 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Test5().setup();
}
});
}
private void setup() {
JFrame frame = new JFrame("Test");
JButton button = new JButton("Click here");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
newFrame();
}
});
}
});
frame.getContentPane().add(button);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
private void newFrame() {
JFrame newFrame = new JFrame("The new frame");
newFrame.setVisible(true);
newFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
CanvasClass canvas = new CanvasClass();
newFrame.getContentPane().add(canvas);
newFrame.pack();
canvas.runAnimation();
}
}
CanvasClass (Canvas子类)
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
public class CanvasClass extends Canvas {
int x;
public CanvasClass() {
setSize(new Dimension(550,550));
this.x = (int) (Math.random() * 255);
}
//@Override
public void paint(Graphics g) {
g.setColor(new Color(x, x, x));
g.fillOval(0,0,500,500);
}
void runAnimation() {
while (true) {
randomise();
repaint();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
void randomise() {
x = (int) (Math.random() * 255);
}
}
答案 0 :(得分:3)
你实际上是在EDT中调用它,但它在canvas.runAnimation();
将要执行的代码放在单独的Thread
(您可以在其中调用睡眠状态),但在repaint()
SwingUtilities.invokeLater()
甚至更好地定义javax.swing.Timer
并在定时器的runAnimation()
actionPerformed()
更新:
int delay = 20; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
canvasInstance.randomise();
canvasInstance.repaint();
}
};
new Timer(delay, taskPerformer).start();
要调用而不是runAnimation()