2

私は Swing アプリケーションを構築しています。機能の一部は、テキストを視覚的および聴覚的に処理および出力する必要があります (Mary TTS を使用)。GUI とテキスト処理クラスが通信するための最良の方法についてアドバイスが必要です。

GUI クラスは JPanel のサブクラスです。その中に、LineProcesser と呼ばれる Runnable を実装するクラスがあり、オーディオ プレーヤーにディスパッチされるテキストを準備します。これをEDTから遠ざけるためにスレッドエグゼキューターを使用しています(これは最善の方法ではないかもしれませんが、私が求めている結果を達成しているようです)。

私の意図は、LineProcessor がすべてのテキストを実行し、各行の終わりで JTextArea を更新することです。さらに、特定の時点で停止してユーザー入力を待つ必要があります。ユーザー入力が完了したら、GUI クラスは処理を再開するよう指示する必要があります。

次のコードは、私が現在持っているものを示しています。

public class MyPanel extends JPanel {
    ExecutorService lineExecutor = Executors.newSingleThreadExecutor();
    Runnable lineProcessor = new LineProcessor();

    public class LineProcessor implements Runnable {

        private int currentLineNo = 0;

            public LineProcessor() {
            //  ...
            }

            @Override
            public void run() {
                // call getText();  
                // call playAudio();
                currentLineNo++;
            }
        }
    }

    private JButton statusLbl = new JLabel();       
    private JButton mainControlBtn = new JButton();

    private void mainControlBtnActionPerformed(ActionEvent evt) {

        if (mainControlBtn.getText().equals("Start")) {
                          lineExecutor.submit(lineProcessor);
                          mainControlBtn.setText("Running");
        }
    }
}

LineProcessor は、変更が必要な GUI コンポーネントをどのように通知し、GUI 内からどのように一時停止および再起動できますか? Swing Worker、プロパティ/イベントリスナー、またはその他のものが必要かどうかについて混乱していますか? 私が読んだ例は理にかなっていますが、ここにあるコードにどのように適用できるかわかりません。

4

3 に答える 3

6

実行する必要があるのは、Swing 呼び出しを Runnable でラップし、SwingUtilities.invokeLater(myRunnable);. それでおしまい。SwingWorker は必要ありません。

例えば、

public class LineProcessor implements Runnable {
  private int currentLineNo = 0;
  Runnable LineProcessor = new LineProcessor();  // won't this cause infinite recursion?

  public LineProcessor() {
     // ...
  }

  @Override
  public void run() {
     // call getText();
     // call playAudio();
     currentLineNo++;

     SwingUtilities.invokeLater(new Runnable() {
        public void run() {
           // *** Swing code can go here ***
        }
     });
  }
}
于 2012-04-28T16:38:08.723 に答える
4

SwingWorker と Event の両方の方法論を使用する必要があります。

  1. 長時間実行されるコードを Swing Worker に配置します。
  2. 新しいプロパティ変更イベント、リスナー、マネージャーを作成する
  3. SwingWorker で、変更イベントが発生したら、PropertyChangeManager を呼び出して、すべてのリスナーに通知します。
  4. イベントの通知を必要とするすべての GUI コンポーネントは、PropertyChangeManager に登録する必要があります。
  5. PropertyChangeManager は、PropertyChangeListener の customProperyChange メソッドを呼び出し、properChangeEvent を渡します。
于 2012-04-28T16:38:43.033 に答える
3

あなたが探しているのはSwingWorkerです。このクラスを使用すると、ワーカー スレッドで作業を実行し、EDT を定期的に更新し、最後に EDT も更新できます。

SO および Swing チュートリアルでいくつかの例を利用できます。ほんの数リンク

メソッドを使用して進行状況を報告できます。これらの結果は、UI を更新できるメソッドにpublish渡されます。process最後に、doneメソッドが呼び出され、最終的な UI 更新を実行できるようになります。

一時停止/再開機能についてはinvokeAndWaitdoInBackgroundメソッド内で をブロック メソッド呼び出しで使用できます (たとえばJOptionPane、ユーザー入力の要求を表示します)。しかし、 で使い始めるinvokeAndWaitと、doInBackgroundを使うのはやり過ぎかもしれません。SwingWorker@Hovercraft Full Of Eels が提案するアプローチを選択するだけです。

于 2012-04-28T16:40:51.247 に答える