我想通过按钮的 ActionListenermain()
的方法使“主线程”(运行的线程启动)做一些工作actionPerformed()
,但我不知道如何实现这一点。
更多上下文:
我目前正在使用 Swing(俄罗斯方块的一种风格)编写 2D 游戏。
当应用程序启动时,会打开一个显示游戏主菜单的窗口。向用户展示了几种可能性,其中之一是通过按下“开始”按钮来开始游戏,这会导致显示游戏面板并触发游戏的主循环。
为了能够在两个面板(主菜单和游戏面板)之间切换,我使用的是 CardLayout 管理器,然后我可以通过调用来显示一个面板show()
。
我的想法是我希望我的开始按钮有一个如下所示的侦听器:
public class StartListener implements ActionListener {
StartListener() {}
public void actionPerformed(ActionEvent e) {
displayGamePanel();
startGame();
}
}
但这不起作用,因为actionPerformed()
是从事件调度线程调用的,所以调用startGame()
(触发主循环:游戏逻辑更新+repaint()
每帧调用)阻塞了整个线程。
我现在处理这个的方式是actionPerformed()
只改变一个布尔标志值:public void actionPerformed(ActionEvent e) {
startPushed = true;
}
然后最终由主线程检查:
while (true) {
while (!g.startPushed) {
try {
Thread.sleep(100);
} catch (Exception e) {}
}
g.startPushed = false;
g.startGame();
}
但我发现这个解决方案非常不雅。
我已经阅读了Swing 中的并发课程,但我仍然感到困惑(我应该实现一个工作线程——这不是有点矫枉过正吗?)。我还没有完成任何实际的多线程工作,所以我有点迷茫。
有没有办法告诉主线程(它将无限期地休眠,等待用户操作)“好的,现在醒来并执行此操作(显示游戏面板并开始游戏)”?
谢谢你的帮助。
编辑: 为了清楚起见,这就是我的游戏循环的样子:
long lastLoopTime = System.currentTimeMillis();
long dTime;
int delay = 10;
while (running) {
// compute the time that has gone since the last frame
dTime = System.currentTimeMillis() - lastLoopTime;
lastLoopTime = System.currentTimeMillis();
// UPDATE STATE
updateState(dTime);
//...
// UPDATE GRAPHICS
// thread-safe: repaint() will run on the EDT
frame.repaint()
// Pause for a bit
try {
Thread.sleep(delay);
} catch (Exception e) {}
}