我正在开发一个带有 Swing GUI 的小型应用程序。应用程序在另一个线程中执行 IO 任务,当该线程完成时,GUI 应相应更新以反射(reflect)线程的操作结果。在 (worker, non-GUI) 中运行的类在构造函数中传递给它的对象将用于更新 GUI,所以我不需要将 GUI 的东西放在非 GUI 类中,而是传递用于更新 GUI 的对象到那个类(class)。
据我了解这里阅读的形式,(线程/Swing )更新(更改)Swing GUI 的安全选项将使用 javax.swing.SwingUtilities.invokeLater()
, javax.swing.SwingUtilities .invokeLaterWait()
和/或 javax.swing.SwingWorker()
基本上做同样的事情。
Swing 的这个全线程问题让我有点困惑,但我需要使用线程在 GUI 应用程序中做任何有意义的事情,而不是在 EDT 中处理时挂起 GUI,所以我现在感兴趣的是:
invokeLater
和invokeLaterWait
是否喜欢向 EDT 发送消息并等待它在处理完该调用之前的消息时执行此操作?从 Swing 线程安全的角度来看,做这样的事情是否正确:
interface IUPDATEGUI { public void update(); } // in EDT/where I can access components directly class UpdateJList implements IUPDATEGUI { public void update() { // update JList... someJList.revalidate(); someJList.repain(); } } class FileOperations implements Runnable { private IUPDATEGUI upObj; List<File> result = new ArrayList<File>; // upObject is accessing this public void FileOperations(IUPDATEGUI upObj) { this.upObj = upObj; } private void someIOTask() { // ... // IO processing finished, result is in "result" } public void run() { someIOTask(); javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { upObj.update(); // access result and update JList } }; ); } }
如果这不正确,那么应该怎么做?
如果可以的话,我宁愿使用 invokeLater
而不是 SwingWorker
,因为我不需要更改我的整个类,而且它在某种程度上更整洁/区分我(例如在 Win32 应用程序中发送消息)。
提前致谢。
最佳答案
使用 invokeLater()
和 invokeAndWait()
将 Runnable 参数传递到 EDT 中等待执行的队列中。因此,当 EDT 能够处理请求时,调用 invokeLater()
将导致 Runnable 在 EDT 中执行。 invokeAndWait()
只是等待(在调用线程中)直到执行发生。
如果您想执行在执行结束时或处于中间状态时通知 EDT 的后台任务,那么使用 SwingWorker 是理想的选择。一个示例是将流程的当前进度传递给 JProgressBar。
对于您的示例,SwingWorker 似乎是更好的选择,但如果您不想过多更改代码,那么在过程完成时调用 invokeLater()
就可以了。
关于java - 使用 invokeLater 或 SwingWorker 从另一个线程更新 Swing 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2247703/