java – 调用事件调度线程在哪里?

前端之家收集整理的这篇文章主要介绍了java – 调用事件调度线程在哪里?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我读到构造Swing组件和处理事件的所有代码必须由Event Dispatch Thread运行.我了解如何通过使用SwingUtilities.invokeLater()方法来实现.考虑以下代码,其中GUI初始化在main方法本身完成
public class GridBagLayoutTester extends JPanel implements ActionListener {   
    public GridBagLayoutTester() {
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();

        JButton button = new JButton("Testing");
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
        button.addActionListener(this);
        add(button,gbc);
    }

    public void actionPerformed(ActionEvent e) {
        System.out.println("event handler code");
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("GridBagLayoutDemo");
        frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);    
        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new BorderLayout());
        contentPane.add(new GridBagLayoutTester(),BorderLayout.CENTER);
        frame.setSize(800,600);
        frame.pack();
        frame.setVisible(true);
        System.out.println("Exiting");
    }   
}

这段代码如何正常工作?我们正在构建JFrame并在主线程中调用主机的其他方法.我不明白这里EDT在哪里(它执行什么代码?). GridBagLayoutTester类的构造函数也是从main方法调用的,这意味着EDT没有运行它.

简而言之

美国东部时间是什么时候开始? (如果在运行此代码的同时启动EDT时,JVM是如何启动EDT的)?
>按钮的事件处理程序代码是否在EDT上运行?

解决方法

代码的工作原理很好,因为您正在构建主线程中的框架,在EDT有机会与之进行交互之前.在技​​术上,你不应该这样做,但技术上你可以在这种具体情况下,因为你不能与JFrame交互,直到它变得可见.

要了解的主要方面是Swing组件不是线程安全的.这意味着它们不能同时被多个线程修改.这通过确保所有修改来自EDT来解决.

EDT是一个致力于用户交互的线程.从用户生成的任何事件总是在EDT上运行.任何在EDT上运行的用户界面更新.例如,当您调用Component.repaint()时,可以从任何线程调用.这只需要设置一个标志,将组件标记为需要油漆,而EDT在下一个循环中进行操作.

EDT自动启动,并且与系统实现相当紧密.它在JVM内处理得很好.通常,它与处理用户交互的窗口系统中的单个线程相关.当然,这是非常依赖于实现.好的是,你不用担心这个.您只需要知道 – 如果您与任何Swing组件交互,请在EDT上执行.

同样,还有另外一件事情很重要.如果您要对外部资源进行任何长时间处理或阻塞,并且您将要响应用户生成的事件来执行此操作,则必须安排在自己的线程中运行EDT.如果您无法执行此操作,则会在等待长时间处理运行时导致用户界面被阻止.优秀的示例是从文件加载,从数据库读取,或与网络交互.您可以使用SwingUtilities.isEventDispatchThread()方法来测试您是否在EDT上(可用于创建可以从任何线程调用的中性方法).

下面是两个代码片段,我在编写处理EDT的Swing编程时经常使用:

void executeOffEDT() {
  if (SwingUtilities.isEventDispatchThread()) {
    Runnable r = new Runnable() {
      @Override
      public void run() {
        OutsideClass.this.executeOffEDTInternal();
      }
    };
    new Thread(r).start();
  } else {
    this.executeOffEDTInternal();
  }
}

void executeOnEDT() {
  if (SwingUtilities.isEventDispatchThread()) {
    this.executeOnEDTInternal();
  } else {
    Runnable r = new Runnable() {
      @Override
      public void run() {
        OutsideClass.this.executeOnEDTInternal();
      }
    };
    SwingUtilities.invokeLater(r);
  }
}

猜你在找的Java相关文章