Java 如何在事件分派线程中等待任务完成,然后继续?

Java 如何在事件分派线程中等待任务完成,然后继续?,java,events,swing,swingworker,Java,Events,Swing,Swingworker,我有一个程序,一个游戏,用Swing制作的GUI GUI由我自己的类组成,该类继承JFrame并持有一个带有CardLayout的JPanel,它有多个JPanel作为卡 其中一个面板上有一个启动游戏的按钮,游戏视图位于其中一张牌上(视图对象有自己的继承JPanel的类,添加到JFrame构造函数中的牌中) 现在是开场白: 我按下JButton,所以我跳转到事件分派线程来执行actionPerformed方法 在这个方法中,我首先翻转到持有视图面板的卡,然后实例化我要玩的关卡和游戏引擎(根据关卡

我有一个程序,一个游戏,用Swing制作的GUI

GUI由我自己的类组成,该类继承JFrame并持有一个带有CardLayout的JPanel,它有多个JPanel作为卡

其中一个面板上有一个启动游戏的按钮,游戏视图位于其中一张牌上(视图对象有自己的继承JPanel的类,添加到JFrame构造函数中的牌中)

现在是开场白:

我按下JButton,所以我跳转到事件分派线程来执行actionPerformed方法

在这个方法中,我首先翻转到持有视图面板的卡,然后实例化我要玩的关卡和游戏引擎(根据关卡实例化)。然后我调用view对象上的repaint(最终应该在应用程序窗口中绘制游戏),然后调用我的游戏引擎对象来启动游戏循环

我的问题是:

当我按下按钮时,游戏引擎开始正常运行(我从控制台的打印中看到),但我的GUI冻结,无法刷新以显示游戏视图。当我删除启动游戏循环的代码片段时,游戏视图通常会显示在屏幕上,但不会移动,因为游戏循环尚未启动

所以我已经推导了,因为在Java中,一切都不是按照编写的顺序发生的,所以在actionperformed方法中的其他操作完成之前,游戏循环开始运行

下面是actionperformed方法的相关片段 科蒂=卡片 肯塔=水平 Valikkopaneli=具有cardlayout的面板 aloitusnappula=开始游戏的按钮 Peli=我创建的继承JFrame的类

if (e.getSource() == aloitusnappula) {
CardLayout kortti=(CardLayout)valikkopaneeli.getLayout(); Kentta Kentta=新Kentta(“testikenta.txt”); 科蒂秀(valikkopaneeli,“Peli”); Peli.this.pack(); Peli.this.setVisible(true); 阿洛伊塔(肯塔); }

下面是aloita(kentta)方法的一个片段:

其中Pelimoottori=游戏引擎类 nakyma=视图对象 peliLooppi()=游戏引擎类中启动游戏循环的方法

如果我从aloita方法中删除moottori.peliLooppi()调用,游戏视图将正常显示

我试着在谷歌上搜索一些答案,我能找到的最远的答案就是和SwingWorker一起搜索,但不知怎么的,这听起来并不是一个很好的方式来做我想做的事情


有什么建议吗?

我想你应该在edt内启动引擎循环。如果是这样,那就糟了

从edt调用另一个线程,并从此新线程管理引擎。对于gui更新,请使用调用edt

或者最好使用一个

要阅读一些关于swing长期工作的优秀英文文档,请参阅。不要使用线程。睡眠

当我删除启动游戏循环的代码片段时,游戏视图会正常显示在屏幕上

听起来您可能正在使用一个带有Thread.sleep的while循环


更好的方法是使用A来安排游戏的“循环”。

如果我使我的游戏引擎可运行,并使run()方法超过游戏循环方法,那么来自游戏循环方法的Thread.sleep调用是否只会停止我的游戏引擎正在运行的线程?抱歉,如果我弄糊涂了。我已经更新了我的贡献,向您推荐了一个教程。所以我应该使用SwingWorker来运行游戏循环?是的,或者使用Swing计时器,如camickr所说。这是你的选择。唯一可以肯定的是不要睡觉。阅读教程,做一些测试,然后…我使用注册到GUI的KeyListener调用的方法在游戏引擎对象中处理按键。我用SwingWorker和Swing Timer正确显示了游戏视图,但两者都有相同的问题,游戏引擎根本不响应键。事实上,KeyListener根本不响应我按下的键。。。
public void aloita(Kentta kentta) {
 moottori = new Pelimoottori(Peli.this, kentta);
 nakyma.repaint();
 moottori.peliLooppi();
}