私はSwing GUI自体がThreadsを使用していると理解しますが、シミュレーションを実行するために別のスレッドを使用しようとしています。私は、Runnableを実装するクラスを作成し、最も簡単なRunnableの例としてカスタムスレッドを使用します。私のrun()メソッドは基本的に私のシミュレーションを実行し、毎秒更新しています(これはうまくいきます)。しかし、私は現在、シミュレーションを一時停止/再開できるボタンを実装しようとしています。 [スタート]ボタンはスレッドを正常に開始し、[一時停止]ボタンはスレッドを正常に一時停止します。ただし、[一時停止]を選択すると、GUI全体が一時停止し、ボタンがまだ選択されているのがわかり、ボタンを選択したり、GUIとやりとりすることができなくなります。カスタムスレッドでwait()を呼び出すとすぐに、このGUIとは別のスレッドを使用していても、私のGUI全体が停止します。 GUIをフリーズしてwait()を呼び出すのはなぜですか?どのように私はGUI全体ではなく、この特定のスレッドだけを一時停止できますか?Javaのwait()とnotify()をフリーズせずに使用するSwing 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です:Thread
オブジェクトにwait
とnotify
を呼び出す
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();
}
}
(1+)nice answer。 –
"呼び出しスレッド"が "現在実行中の"スレッドよりも適切な記述であることを除いて、素晴らしい答えです。 –
十分に公正。それに応じて編集。 –