如何忽略事件派发线程允许该程序工作?

DSl*_*r64 7 java invokelater event-dispatch-thread

我试图看看今天早些时候是否可以回答这个问题.我意识到我并不完全理解Event Dispatch Thread(EDT).谷歌搜索确认并帮助了这一点,并澄清了为什么我没有.(也可能与理解有关.)

代码设置GUI,稍后(如前面的问题中所述)更新文本字段,直到取消设置标志.

我有几个问题/要求.

  • 请解释为什么如果两个调用(to swingInitdoIt)都在invokeLater块之外(如图所示),下面的代码运行正常,因为这两个调用都影响或查询GUI但是它们都没有在EDT上执行(是吗?).这不是诱人的失败吗?

  • 如果呼叫在swingInit内部和doIt外部,代码也会运行invokeLater.所以swingInit在EDT上执行,但不应该doIt在EDT上执行是一个问题吗?(我觉得这很有效.我应该去过吗?)

  • 我想我明白为什么它会挂起,如果doIt它在里面invokeLater而不管它在哪里swingInit:目的invokeLater只是初始化 GUI(对吧?).

  • 如果doIt只启动(可能发生的事件)在美国东部时间,但肯定不是里面invokeLater块?

(EDT概念的历史很有意思.它并不总是如此.请参阅上面的链接"我为什么不"理解它.)

import static java.awt.EventQueue.invokeLater;
import java.awt.event.*;
import javax.swing.*;

public class Whatever 
{
  static boolean flag = true;
  static JTextField tf = new JTextField("Hi",20);
  static JPanel p = new JPanel();
  static JFrame f = new JFrame();
  static JButton b = new JButton("End");

  public static void main(String[] args)
  {
    swingInit();

    invokeLater
    (
      new Runnable()
      {
        @Override
        public void run() 
        {
    //    swingInit();
    //    doIt();
        }
      }
    ); 
   doIt();      
  } 

  static void swingInit()
  {
     b.addMouseListener
    (
        new MouseAdapter()
        {
          @Override
          public void mouseClicked(MouseEvent e)
          {
            flag = false;
            JOptionPane.showMessageDialog(null,"Clicked... exiting");
            System.exit(0);
          }
        }
    );

    p.add(tf);
    p.add(b);
    f.add(p);
    f.setVisible(true);
    f.pack();
    f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
  }

  static String getInfo(){
    return "Hello... " + Math.random();
  }

  static void doIt(){
    while(flag)     
      tf.setText(getInfo());
  }; 
}
Run Code Online (Sandbox Code Playgroud)

cop*_*peg 3

列出你的每一个要点:

  • 代码在主线程上启动 - EDT 并行运行。 swingInit构造 UI 后返回,然后由 EDT 控制,允许dotIt在主线程上并行执行操作

  • 与上面的情况类似,但这里您保证在 EDT 上构建 UI(按照Oracle的建议)。

  • 长时间运行的任务被放置在 EDT 上,防止其显示(如果放置在之前swingIt)或绘画和交互(如果放置在之后)。the purpose of invokeLater is ONLY to initialize the GUI目的是将非线程安全的 Swing 调用放置到 EDT 上。如果在主要方法中,我建议使用SwingUtilities.invokeAndWait

  • 如果您希望像这样更新 UI,请考虑使用SwingTimer.

在 EDT 之外运行 EDT 特定的非线程安全代码并不能保证失败,但它确实会导致失败(当两个(或更多)线程尝试同时更新数据时发生冲突)。

我曾经花了几个小时追踪一个神秘的问题NullPointerException,却发现问题LookAndFeel所在的电话不在 EDT 上。学过的知识。