我正在构建一个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,属性/事件监听器或其他东西感到困惑?我读过的例子很有意义,但我看不出如何将它们应用到我这里的代码中。
答案 0 :(得分:6)
您需要做的就是在Runnable中包装任何Swing调用,并通过SwingUtilities.invokeLater(myRunnable);
在EDT上对其进行排队。而已。不需要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 ***
}
});
}
}
答案 1 :(得分:3)
您必须同时使用SwingWorker和事件方法。
答案 2 :(得分:3)
您要找的是SwingWorker
。这个类允许在工作线程上执行工作,在EDT上定期更新,最后也更新EDT。
有关SO和Swing教程的几个示例。只需几个链接
SwingWorker
SwingWorker
javadoc 可以使用publish
方法完成报告进度,这些结果将传递到您可以更新UI的process
方法。最后,调用done
方法,允许您执行一些最终的UI更新。
对于暂停/重启功能...您可以使用invokeAndWait
方法中的doInBackground
使用阻止方法调用(例如,显示要求用户输入的JOptionPane
)。但是如果你开始在invokeAndWait
中使用doInBackground
,使用SwingWorker
可能会有点过分,你可以选择@Hovercraft Full Of Eels建议