我有几个关于 Swing 和使用 EDT 进行 GUI 更新的问题。我刚开始阅读这些东西,所以我是这个领域的初学者:
- 在 EDT 上运行需要哪些操作?如果他们不这样做,是否只是引发了异常?
- 是否有任何特定时间我们实际上会自动进入 EDT?
- 如果我们使用调度任务,
SwingUtilities.invokeLater
我们会将它排入当前的 GUI 更新任务队列(EDT),对吗? - 对上述队列的访问我猜是同步的,或者使用了一些并发集合,但是如果我从两个后台线程调度两个GUI更新任务,则无法说先添加哪个?例如,如果线程 1 FIRST 提交将 JLable 的文本设置为“是”的任务,然后不久之后,第二个线程出现并提交将该值设置为“否”的任务,我们是否保证结果将是“是”,还是仅仅是操作系统如何安排这些事情的问题?
SwingWorker 如何确保该
done()
方法在 EDT 上运行?它设置以下代码:future = new FutureTask<T>(callable) { @Override protected void done() { doneEDT(); setState(StateValue.DONE); } };
所以我想知道 FutureTask 是否以某种方式确保它invokeLater
被调用?
感谢您的所有回答。
一个好的规则是所有操作(访问/更新/...)都应该在 EDT 上进行。javadoc 中提到了一些例外(某些类的某些方法),但它们很难记住,因此坚持“在 EDT 上做所有事情”的方法更容易。不会引发异常(幸运的是,JavaFX 修复了这个缺点)。您可以使用自定义
RepaintManager
来检测大多数此类违规行为:请参阅本文。用户触发的一切都在 EDT 上处理。例如,如果用户点击一个按钮,
actionPerformed
相应的Action
orActionListener
将在 EDT 上被调用。正确的
您首先安排的事情将首先执行。该
invokeLater
调用只是Runnable
在队列末尾添加。invokeLater
稍后使用第二次将Runnable
在先前安排的之后添加这个新的Runnable
。看一下代码
doneEDT
private void doneEDT() { Runnable doDone = new Runnable() { public void run() { done(); } }; if (SwingUtilities.isEventDispatchThread()) { doDone.run(); } else { doSubmit.add(doDone); } }