gpt4 book ai didi

java - invokeLater 未按预期工作(JButton 从未释放)

转载 作者:行者123 更新时间:2023-12-01 22:30:36 26 4
gpt4 key购买 nike

我有:

  • 上面有 JButton 的 JFrame。
  • 用于显示动画的单独 Canvas 子类。

我希望在按下 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);
}
}

最佳答案

您实际上在 EDT 中调用它,但它在 canvas.runAnimation();

中被阻止

将要执行的代码放在单独的Thread中(您可以在其中调用 sleep),但在 SwingUtilities.invokeLater()< 中调用 repaint()/

或者更好的是定义一个 javax.swing.Timer 并在计时器的 actionPerformed() 中调用 runAnimation()

更新:

  int delay = 20; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
canvasInstance.randomise();
canvasInstance.repaint();
}
};
new Timer(delay, taskPerformer).start();

被调用而不是 runAnimation()

关于java - invokeLater 未按预期工作(JButton 从未释放),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27839773/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com