gpt4 book ai didi

java - 如何创建另一个线程,以便在行星模拟运行时我的 ActionListener 仍然监听按钮按下事件?

转载 作者:行者123 更新时间:2023-12-01 11:56:50 25 4
gpt4 key购买 nike

我有一个 JButton 并为其添加了一个 ActionListener。我还有一个 SimulationPanel 类,它扩展了 JPanel 并有一个名为 simulationPanel 的实例。两者都添加到 JFrame 中。在 ActionListeneractionPerformed 方法中,我调用 simulationPanel.startSimulation()

class StartButtonListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent arg0) {
if(mode == MODE_DEFAULT){
mode = MODE_SIMULATING;
startButton.setText("Stop Simulation");
simulationPanel.startSimulation();
} else if(mode == MODE_SIMULATING){
mode = MODE_DEFAULT;
startButton.setText("Start Simulation");
simulationPanel.stopSimulation();
}
}
}

stopSimulation() 方法将 running 设置为 false。

public void startSimulation() {
running = true;
long time = System.currentTimeMillis();
long time2 = System.currentTimeMillis();
while(running){
time = System.currentTimeMillis();
if(time - time2 > 1000/60){
for(int i = 0; i < planets.size(); i++) {
planets.get(i).setLocation(planets.get(i).getNewLocation());
}
this.paintImmediately(0, 0, 950, 680);
time2 = System.currentTimeMillis();
}
}
}

这会设置我的行星的新位置,并每 60 秒重新绘制一次屏幕。

问题是,一旦进入 while(running) 循环,ActionListener 就不再响应按下的按钮,因此无法执行 stopSimulation()叫。我将如何创建一个新线程,使按钮能够在模拟运行时做出响应?

The entire program

最佳答案

Swing 是单线程环境,如果您阻塞事件调度线程,那么它就无法处理事件队列,这涉及到处理用户输入和获取事件。

当您需要执行长时间运行的任务时,您应该将该任务卸载到另一个线程。

请记住,Swing 也不是线程安全的,这意味着您永远不应该从事件调度线程的上下文之外创建或修改 UI。

您可以使用一些工具来让您在这方面的生活变得更轻松。

您可以使用 SwingWorker,它允许您在后台运行长时间运行/阻塞任务,但使用 publish/process 向 UI 发送更新的方法,不违反 Swing 的单线程规则

您可以使用 Swing Timer,它允许您安排在 EDT 上下文中执行的定期回调,从而可以安全地从内部更新 UI

您可以使用普通的旧 Thread 并使用 SwingUtilities.invokeLater 与 EDT 同步更新,但我不喜欢这种方法,因为它很痛苦通过传递状态信息

关于java - 如何创建另一个线程,以便在行星模拟运行时我的 ActionListener 仍然监听按钮按下事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28386644/

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