Java Swing - 在EDT上运行

时间:2012-08-06 09:03:50

标签: java swing event-dispatch-thread

关于Swing和使用EDT进行GUI更新,我有几个问题。我刚刚开始阅读这些内容,所以我是这个领域的初学者:

  1. 在EDT上运行需要哪些操作?如果他们不这样做,只是提出一个例外?
  2. 我们实际上是自动加入EDT时是否有特定时间?
  3. 如果我们使用SingUtilities.invokeLater安排任务,我们将它排入GUI更新任务的当前队列吗?
  4. 访问上面的队列我猜是同步的,或者使用了一些并发集合,但如果我从两个后台线程安排两个GUI更新任务,就不可能说先添加哪一个?例如,如果线程1 FIRST提交将JLable的文本设置为“是”的任务,然后,短时间之后,第二个线程出现并提交将该值设置为“no”的任务,我们是否保证结果将是“是”,或者仅仅是操作系统如何安排这些事情的问题?
  5. SwingWorker究竟如何确保在EDT上运行done()方法?它设置以下代码:

      future = new FutureTask<T>(callable) {
                   @Override
                   protected void done() {
                       doneEDT();
                       setState(StateValue.DONE);
                   }
               };
    
  6. 所以我想知道FutureTask是否确保调用invokeLater

    感谢您的所有答案。

4 个答案:

答案 0 :(得分:14)

  1. 一个好的规则是所有操作(访问/更新/ ......)都应该在EDT上进行。 javadoc中提到了一些例外(某些类的某些方法),但它们很难记住,更容易坚持“在EDT上做所有事情”的方法。不会例外(幸运的是,JavaFX解决了这个缺点)。您可以使用自定义RepaintManager来检测大多数违规行为:请参阅this article
  2. 用户触发的所有内容都在EDT上处理。例如,如果用户点击某个按钮,则会在EDT上调用相应actionPerformedAction的{​​{1}}。
  3. 正确
  4. 您首先执行的事项将首先执行。 ActionListener调用只是在队列末尾添加invokeLater。稍后再次使用Runnable会在之前安排的invokeLater之后添加新的Runnable
  5. 查看Runnable

    的代码
    doneEDT

答案 1 :(得分:8)

  1. 基本上,每次使用Swing组件或Swing组件的模型时,都必须在EDT中完成。如果不这样做,则不会引发任何例外。它可以工作,但也可能无法工作,行为不稳定,数据损坏等等。
  2. 在EDT中调用每个Swing事件侦听器。基本上,除了main方法之外,Swing应用程序的每一行代码都默认在EDT中执行,除非您明确地启动一个线程,使用SwingWorker或类似的东西。
  3. 提交给SwingUtilities.invokeLater()的任务按照与提交顺序相同的顺序执行。
  4. 在内部,它使用SwingUtilities.invokeLater()或类似的方法。 FutureTask与Swing没有任何关系。 SwingWorker确保在EDT中执行其done方法。 doneEDT()方法有以下注释:在EDT上完成调用

答案 2 :(得分:0)

SwingWorker确保通过以下代码在EDT上运行done()方法:

    Runnable doDone =
        new Runnable() {
            public void run() {
                done();
            }
        };
    if (SwingUtilities.isEventDispatchThread()) {
        doDone.run();
    } else {
        doSubmit.add(doDone);
    }

实际上它将doDone变量添加到AccumulativeRunnable doSubmit,

查看AccumulativeRunnable.java的源代码,你会发现它有以下代码

protected void submit(){

SwingUtilities.invokeLater(本);

}

这就是为什么swingworker确保在EDT上运行方法done()的原因

答案 3 :(得分:-1)

1。在Java GUI应用程序中,main()方法在 Event Dispatcher Thread中安排GUI的构建后不长,main() 方法退出...现在它的EDT负责处理GUI。

2. 所以我们不需要在EDT上启动我们的应用,自动完成。

3 始终保持UI工作在UI线程上,非UI工作在非UI线程上。

所以请始终保留您的EDT线程,这是仅用于GUI工作的GUI线程。

例如:

public static void main(String[] args){
    EventQueue.invokeLater(new Runnable(){
          public void run(){    
            myframe.setVisible(true);
         }
     }
}

4. 创建一个单独的非UI线程来处理这个长时间的处理方法。

5. 您可以简单地使用Thread或使用专门引入Java的SwingWorker来同步UI和非UI线程。

6. :SwingWorker不会确保在EDT上运行done()方法,而是将其输出同步到EDT线程,这是GUI线程。