[英]How to randomly communicate with a process without freezing the GUI in Java Swing?
[英]Using Java wait() and notify() without freezing Swing GUI
我知道Swing GUI本身使用线程,但是我试图使用单独的线程来运行仿真。 我创建了一个实现Runnable的类,并像大多数简单的Runnable示例一样使用自定义线程。 我的run()方法基本上运行我的仿真,每秒更新一次(效果很好),但是我现在尝试实现可以暂停/恢复仿真的按钮。 我的开始按钮成功启动线程,我的暂停按钮成功暂停线程。 但是,选择“暂停”后,整个GUI会暂停,您可以看到该按钮仍处于选中状态,而我完全无法选择任何按钮或无法与该GUI进行交互。 一旦我在自定义线程上调用wait(),我的整个GUI就会暂停,即使我正在使用与此GUI分开的线程。 为什么调用wait()冻结了我的GUI? 如何仅暂停该特定线程而不暂停整个GUI?
请注意,“开始”按钮应使程序继续运行。 这是我的GUI代码:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GridFrame extends JFrame {
private static final long serialVersionUID = 2857470112009359285L;
private MyGridPanel grid;
private Simulation sim;
GridFrame(Simulation sim, int w, int h, int rows, int cols) {
this.sim = sim;
setTitle("Simulation");
setSize(w, h);
grid = new MyGridPanel(w, h, rows, cols);
add(grid, BorderLayout.CENTER);
//Build bottom panel
JPanel buttons = new JPanel();
buttons.setLayout(new GridLayout(1,3));
JButton start = new JButton("Start");
JButton pause = new JButton("Pause");
JButton reset = new JButton("Reset");
start.setActionCommand("Start");
start.addActionListener(new ButtonActionListener());
pause.setActionCommand("Pause");
pause.addActionListener(new ButtonActionListener());
reset.setActionCommand("Reset");
reset.addActionListener(new ButtonActionListener());
buttons.add(start);
buttons.add(pause);
buttons.add(reset);
add(buttons, BorderLayout.SOUTH);
}
public MyGridPanel getGrid(){
return grid;
}
private class ButtonActionListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
switch(e.getActionCommand()){
case "Start":
System.out.println("Start");
sim.start();
break;
case "Pause":
System.out.println("Pause");
sim.pause();
break;
case "Reset":
System.out.println("Reset");
break;
}
}
}
}
这是我的Runnable:
public class Simulation implements Runnable{
private Thread t;
private GridFrame frame;
private boolean paused;
public Simulation(){
frame = new GridFrame(this, 300, 300, 10, 10);
frame.setVisible(true);
paused = true;
}
public void start () {
if(t == null){
//Thread has not been created. Simulation has not started to run yet
System.out.println("Starting thread.");
t = new Thread(this);
t.start();
paused = false;
}
else if(paused){
//Simulation and thread already started to run but was paused. This should use notify() to resume the thread.
resume();
paused = false;
}
}
public void resume(){
synchronized(t){
t.notify();
}
}
public void pause(){
synchronized(t){
try {
t.wait();
paused = true;
} catch (InterruptedException e) {
System.out.println("Exception when trying to pause simulation");
e.printStackTrace();
}
}
}
@Override
public void run() {
while(true){
frame.getGrid().step();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Thread interrupted while simulation was running.");
e.printStackTrace();
}
}
}
public static void main(String[] a) {
Simulation s = new Simulation();
}
}
在Thread
对象上调用wait
和notify
行为与在任何其他对象上的行为没有什么不同。 具体来说,正如您所注意到的,它不会向执行线程发送应暂停的信号,而是会阻塞调用线程(在这种情况下为您的UI线程),直到收到notify
消息为止。
您将需要实现一个从UI线程到后台线程的消息传递系统(例如阻塞队列),以获取所需的内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.