2

我正在构建一个 Swing 应用程序,其中一部分功能应该是处理和输出一些视觉和听觉的文本(使用 Mary TTS)。我需要一些关于 GUI 和文本处理类进行通信的最佳方式的建议。

GUI 类是 JPanel 的子类。其中我有一个实现 Runnable 的类,称为 LineProcesser,它准备发送到音频播放器的文本。我正在使用一个线程执行器来阻止这个 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 来通知所有的 lisener。
  4. 所有希望收到事件通知的 GUI 组件都应向 PropertyChangeManager 注册。
  5. 您的 PropertyChangeManager 将调用 PropertyChangeListener 的 customProperyChange 方法并将传递 propertyChangeEvent
于 2012-04-28T16:38:43.033 回答
3

您正在寻找的是一个SwingWorker. 此类允许在工作线程上执行工作,定期更新 EDT,并最终更新 EDT。

SO 和 Swing 教程中提供了几个示例。只是几个链接

可以使用publish方法报告进度,这些结果将传递给process可以更新 UI 的方法。最后,done调用该方法允许您执行一些最终的 UI 更新。

对于暂停/重启功能......您可以invokeAndWaitdoInBackground方法中使用带有阻塞方法调用的方法(例如显示JOptionPane询问用户输入)。但是,如果您开始使用invokeAndWaitin ,doInBackground使用 the 可能有点过头了SwingWorker,您可以简单地选择@Hovercraft Full Of Eels 建议的方法

于 2012-04-28T16:40:51.247 回答