Java Swing - 在 EDT 上运行

2022-09-04 00:57:59

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

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

      future = new FutureTask<T>(callable) {
                   @Override
                   protected void done() {
                       doneEDT();
                       setState(StateValue.DONE);
                   }
               };
    

所以我想知道FutureTask是否以某种方式确保它被称为?invokeLater

感谢您的所有回答。


答案 1
  1. 一个好的规则是,所有操作(访问/更新/...)都应该在EDT上进行。javadoc(某些类的某些方法)中提到了一些例外,但它们很难记住,因此更容易坚持“在EDT上做任何事情”的方法。不会出现异常(幸运的是,JavaFX修复了这个缺点)。您可以使用自定义来检测大多数此类违规行为:请参阅此文章RepaintManager

  2. 用户触发的所有内容都在 EDT 上处理。例如,如果用户单击某个按钮,则相应的 或 将在 EDT 上调用。actionPerformedActionActionListener

  3. 正确

  4. 您首先计划的事情将首先执行。该调用只是在队列的末尾添加 。稍晚使用第二次将在先前计划之后添加此新内容。invokeLaterRunnableinvokeLaterRunnableRunnable

  5. 查看代码doneEDT

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

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

推荐