这样一段代码:
private void log(String message) {
LogBox.append(message + "\n");
}
private void log(Exception e) {
log(e.getMessage());
}
private void ConvertButtonActionPerformed(java.awt.event.ActionEvent evt) {
String url = UrlBox.getText();
if (url.isEmpty()) {
log("Empty URL");
return;
}
LogBox.setText("");
try {
log("URL "+url+" accepted. Trying to download...");
String content = URLConnectionReader.getText(url);
log("Downloaded. Parsing the content...");
//
} catch (Exception e) {
log(e);
}
}
应该在每次 log
调用后立即将每条消息输出到 LogBox
(JTextArea
),但输出 URL ... accepted
仅当 URLConnectionReader.getText(url)
完成时。
有几种方法可以立即输出:
- Visual Basic 6 和 .NET 中的 Application.DoEvents
- Delphi 中的 Application.ProcessMessages
是否有一些简单的方法可以立即输出?我正在研究有关 DoEvents 以及如何在 Java 中执行此操作的问题,但我认为从多线程开始学习 Java 不是正确的方法。
最佳答案
创建一个 SwingWorker
来进行下载:http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
ActionListener
的作用就是:监听用户操作,并启动程序对该操作的响应。
有时候,程序的 react 很快,而且只涉及到GUI。例如,在计算器应用程序中,您可以将监听器附加到计算当前表达式的结果并将其写入文本框的“等于”按钮。这一切都可以在监听器方法中完成(尽管您可能希望分离行为以进行测试)。
如果对用户操作的响应是启动一些长时间运行的过程,例如下载和解析文件,那么您不希望在监听器主体中执行此操作,因为它会卡住 UI。相反,从监听器中收集任何信息(在您的情况下为 URL 值),并启动一个 SwingWorker
来处理程序的响应。
在我的评论中,我建议将 getText()
之后的所有内容移动到 SwingWorker
中。这是因为,对我来说,响应是“如果您有有效的 URL,请下载一个文件,并记录进度”。正如我所见,测试空字符串是该响应的一部分。如果您想将空字符串测试留在监听器中,那很好,但我觉得它的可测试性较差。
您必须将对getText()
的调用留在监听器主体内,因为您只能从事件分发线程访问Swing 组件。如果您将该调用移至 worker,那么它可能会在文本框更新自身的同时访问文本框,从而导致数据损坏。
关于java - 在 Java Swing GUI 中立即输出文本的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17408136/