イベントディスパッチスレッド(EDT)は、GUIの読み取りまたは更新が安全な唯一のスレッドです。
一時停止ボタンは、イベントディスパッチスレッドのオン/オフ変数を設定する必要があります。
時間がかかる操作とループはではなく、がEDTに属している必要があります。 (ループは何もせずに変数をチェックし続けることも、すべてのCPUを簡単に食べることもできます。それ以外に何もする必要がない場合は、確認してからに電話してください(例えば100ms)。
オン/オフ変数がOFFに設定されていることが証明できますが、常にONとして読み取られると、変数の値がEDTからワーカー・スレッドにコピーされていない可能性があります。 volatile
、またはsynchronize
にアクセスするか、AtomicReference
を使用するか、SwingUtilities.invokeAndWait()
を使用してEDTで読み取ります。
SwingWorker
おそらくはここでは最も簡単な方法です。時間がかかる操作と、doInBackground()
メソッドのオン/オフチェックと、done()
メソッドのGUI更新を実装します。
public enum State {
RUNNING, STOPPED
}
public class ThreadSafeStateModel {
private State state = State.STOPPED;
public synchronized void stop() {
state = State.STOPPED;
}
public synchronized void start() {
state = State.RUNNING;
}
public boolean isRunning() {
return state == State.RUNNING;
}
}
public class ExpensiveProcessWorker extends SwingWorker<Void, Void> {
private final ThreadSafeStateModel model;
public ExpensiveProcessWorker(ThreadSafeStateModel model) {
this.model = model;
}
@Override // Runs in background
protected Void doInBackground() throws Exception {
while (model.isRunning()) {
// do one iteration of something expensive
}
return null;
}
@Override // Runs in event dispatch thread
protected void done() {
// Update the GUI
}
}
public class StopButton extends JButton {
public StopButton(final ThreadSafeStateModel model) {
super(new AbstractAction("Stop") {
@Override
public void actionPerformed(ActionEvent e) {
model.stop();
}
});
}
}
public class StartButton extends JButton {
public StartButton(final ThreadSafeStateModel model) {
super(new AbstractAction("Start") {
@Override
public void actionPerformed(ActionEvent e) {
model.start();
new ExpensiveProcessWorker(model).execute();
}
});
}
}
(多くは、実際のアプリケーションに応じて、これをクリーンアップするために行うことができるが、あなたのアイデアを得る。)
すべてがOKで、完璧に動作しますあなたのデビッドありがとうございます。 しかし、ちょっとしたこと:私は、GUIをリフレッシュするためにdone()メソッドを使う必要はありませんでした。私はdoInBackground()メソッドで成功する。 あなたはそれについて考えていますか? –
Jeremyさん、一般的には 'doInBackground()'のUIを更新することはよくありますが、あなたはそれに依存することはできません。 UIは常にイベントディスパッチスレッドに描画され、UIモデルは常にイベントディスパッチスレッドで読み込まれるため、イベントディスパッチスレッドのUIモデルに書き込む方が安全です。たとえば、 'TableModel'の行数がイベントディスパッチスレッドの外側で変更された場合、テーブルの描画時に' IndexOutOfBoundsException'が発生する可能性が高くなります。 –
私は理解しています...もう少し多くのGUIアップデートを追加しようとしましたが、フリーズしました。この問題を解決するために、done()メソッドを使用してGUIを更新し、同じ初期データを持つ他のswingWorkerを作成しました。今は大丈夫です!どうもありがとうございました! –