此刻,我正在为自己的娱乐工作制作康威的生命游戏。到目前为止,一切都进展顺利,但就在我测试一些最终部件时,我发现了一个令人恼火的错误。代码的主体发生在while循环内,while循环由用户希望看到的游戏的“世代”数控制。当这个循环正在执行时,JFrame的红色X拒绝响应,我不知道为什么会这样。
我遇到此问题的区域:
public void run(int steps) throws InterruptedException{
int a = 0;
do{
step();
myDisp.update(myDisp.getGraphics());
Thread.sleep(delay);
a++;
}while(a < steps);
}
答案 0 :(得分:6)
我建议你把这种处理放在一个单独的线程中。 只要将其保存在代码的主体中,只要循环正在运行,Swing组件就不会响应任何用户交互。
在this page中,您可以找到一些有关Swing应用程序中异步操作的良好实践。我想强调其中一个主题:
规则#2:不要在事件线程上运行耗时的操作。
我将继续重复这一点:Swing对所有GUI事件使用单个线程。如果您的事件处理程序正在通过网络上传一个多兆字节的文件,那么这些事件将被延迟,直到您完成为止。这个规则涉及一个平衡行为:某些操作(例如获取文件的大小)非常快,以至于它们不会中断用户。但是,这不是一个骑士的理由,因为有一天你的用户将获得驻留在具有间歇性网络连接的文件服务器上的文件的大小。
This other page还显示了如何在Swing应用程序中处理长时间运行的任务的示例。您可能还想查看SwingWorker类。
答案 1 :(得分:4)
默认情况下,while循环将在事件调度线程(EDT)上执行,该线程处理所有GUI操作。因此,您永远不应该在EDT上执行长时间运行的任务 - GUI将锁定,因为您没有给它任何空闲时间来处理用户输入!但是,必须执行任何触及EDT上GUI的代码。有一个特殊的方法SwingUtilities.invokeLater()
,它将执行此操作(使用Runnable并在EDT上调用它。)
因此,在您的示例中,您将创建一个新线程并执行它,此线程将包含您的while循环,并且myDisp.update()
调用将包含在上述方法中以确保它仍在EDT上。另一种(整洁的)解决方案是使用SwingWorker
,它提供了一个更好的界面来完成同样的事情。
答案 2 :(得分:3)
您的长时间循环正在Swing E 发泄 D ispatch T hread或EDT上运行,输入并预防所有Swing图形和用户交互。解决方案:为长期运行的任务使用后台线程。
请阅读:Lesson: Concurrency in Swing
有关此内容以及如何使用SwingWorker的更多详细信息。