0

理解できないことがあります。SwingGUIに「再生」ボタンと「一時停止」ボタンがあります。「ON」と「OFF」の状態を定義する静的変数もあります。(メインプログラムはGUIを生成します)。「play」をクリックすると、静的変数の状態が「ON」に変更され、GUIも変更するスレッドで時間のかかるプロセスが起動します。静的変数が「ON」である限り、同じプロセスでループします。「一時停止」をクリックすると、静的変数がオフに変更されます。しかし、「再生」をクリックすると、GUIがフリーズし、その結果、次のようになります。

  1. GUIが更新されない
  2. 「一時停止」ボタンでプロセスを「一時停止」することはできません。

EDTとSwingWorkerについて聞いたことがありますが、それを行う簡単な方法があります。

あなたの助けに感謝し、私の悪い英語を許してください...

4

6 に答える 6

6

問題は、GUIの更新を担当する同じスレッドで集中的で時間のかかる作業を行っていることです。SwingWorkerを使用すると、時間のかかるタスクを別の実行スレッドに移動できるため、UIスレッドはその処理を妨げられずに実行できます。

ただし、それはさらに複雑な問題を追加します:親和性。UIコンポーネントでメソッドを呼び出すには、通常、UIスレッドから呼び出す必要があります。したがって、ワーカースレッドからUIスレッドに戻るには、特別な機能を使用する必要があります。SwingWorkerもこの機能を提供します。

このドキュメントを一読することをお勧めします。

于 2009-08-07T08:36:25.393 に答える
3

EDTとSwingWorkersがどのように動作するかを理解するには、Swingの同時実行性を読む必要があります。

すべてのGUI更新はEDTで実行されるため、GUIコンポーネントをクリックすると、この呼び出し元のメソッドがEDTで実行されます。これが時間のかかるプロセスである場合、これにより、EDTはそれ以上のGUI更新を実行できなくなります。したがって、GUIがフリーズし、一時停止ボタンをクリックできません。

別のスレッドで時間のかかるプロセスを実行するには、SwingWorkerを使用する必要があります。上記のリンクで、これを行う方法について詳しく説明しています。

于 2009-08-07T08:38:14.127 に答える
0

Swingのイベントハンドラーで長時間実行プロセスを開始しないでください。GUIがフリーズするためです。:)新しいスレッドで開始します。ワーカースレッドからGUIを操作することを計画している場合にのみ、を使用する必要がありSwingWorkerます(Swingはスレッドセーフではないため)。

于 2009-08-07T08:36:32.460 に答える
0

これは非常に単純な理由です。Javaが時間のかかるプロセスに取り組んでいる間は、GUIを更新できません。解決策:時間のかかるプロセスを別のスレッドで実行します。それをプログラムする方法はたくさんあります、そしてそれはおそらくあなたのプログラムがどのように書かれているかにいくらか依存するでしょう。

于 2009-08-07T08:37:18.183 に答える
0

イベントディスパッチスレッド(EDT)は、GUIを安全に読み取ったり更新したりできる唯一のスレッドです。

一時停止ボタンは、イベントディスパッチスレッドでオン/オフ変数を設定する必要があります。

時間のかかる操作とループは、EDTに含めるべきではありません。(ループは、変数をチェックする以外に何もせずに継続的に実行するべきではありません。そうしないと、CPUをすべて簡単に使い果たす可能性があります。他に何もすることがない場合は、チェックしてから、Thread.sleep()しばらくの間(たとえば、100ms)呼び出します。)

オン/オフ変数がオフに設定されていることを証明できるが、それでも常にオンとして読み取られる場合は、変数の値がEDTからワーカースレッドにコピーされていない可能性があります。作成するvolatileか、synchronizeアクセスするか、を使用するか、を使用AtomicReferenceしてEDTで読み取りますSwingUtilities.invokeAndWait()

SwingWorkerここでは、おそらく最も簡単な方法です。時間のかかる操作とオン/オフチェックをdoInBackground()メソッドに実装し、GUIの更新をメソッドに実装しますdone()

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();
            }
        });
    }
}

(実際のアプリケーションによっては、これをクリーンアップするために多くのことを行うことができますが、アイデアは得られます。)

于 2009-08-07T09:05:04.197 に答える