Java 确定事件分派线程的范围

Java 确定事件分派线程的范围,java,multithreading,swing,event-handling,event-dispatch-thread,Java,Multithreading,Swing,Event Handling,Event Dispatch Thread,我对荡秋千还不熟悉,但仍在学习它的来龙去脉。我编写了一个基本代码,并开始尝试EDT。代码如下: public class SwingDemo2 extends Thread implements ActionListener { JLabel jl; SwingDemo2() { JFrame jfr = new JFrame("Swing Event Handling"); jfr.setSize(250, 100); jfr.setDefaultCloseOper

我对荡秋千还不熟悉,但仍在学习它的来龙去脉。我编写了一个基本代码,并开始尝试EDT。代码如下:

public class SwingDemo2 extends Thread implements ActionListener {

JLabel jl;

SwingDemo2() {
    JFrame jfr = new JFrame("Swing Event Handling");
    jfr.setSize(250, 100);
    jfr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    jl = new JLabel("Press a button!", SwingConstants.CENTER);

    System.out.println("After Label: " + SwingUtilities.isEventDispatchThread());

    JButton jb1 = new JButton("OK");
    jb1.setActionCommand("OK");

    jb1.addActionListener(this);

    JButton jb2 = new JButton("Reset");
    jb2.setActionCommand("Reset");

    jb2.addActionListener(this);

    jfr.add(jl, BorderLayout.NORTH);
    jfr.add(jb1, BorderLayout.WEST);
    jfr.add(jb2, BorderLayout.EAST);

    System.out.println("After adding: " + SwingUtilities.isEventDispatchThread());

    jfr.setVisible(true);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            System.out.println("In main: " + SwingUtilities.isEventDispatchThread());
            new SwingDemo2();
        }
    });
}

public void actionPerformed(ActionEvent ae) {
    if (ae.getActionCommand() == "OK") {
        System.out.println("In OK: " + SwingUtilities.isEventDispatchThread());
        jl.setText("You pressed Ok");
    }
    else if (ae.getActionCommand() == "Reset") {
        System.out.println("In Reset: " + SwingUtilities.isEventDispatchThread());
        jl.setText("You pressed Reset");
    }

}

}
我添加了几个
isEventDispatchThread()
方法来验证我所在的线程。 除GUI外,控制台中的消息包括:

In main: true
After Label: true
After adding: true
In OK: true
In Reset: true
我似乎一直在参加EDT。我的问题是,在
jfr.setVisible(true)
语句之后,
SwingDemo2()
构造函数不应该返回
main()
吗?这不应该是EDT的结束吗

在我第一次按下GUI中的任何按钮之前,我等待了很多秒,那么为什么我的事件处理仍然在EDT中进行呢?这不应该给EDT足够的时间终止吗


先走一步

在事件调度线程中,可以看到“事件”一词。这意味着所有(UI)“事件”总是在该特定线程上调度:ActionEvent、PaintEvent、KeyEvent、MouseeEvent等。。。您可以等待多长时间,EDT上将始终发送按钮单击(ActionEvent)


当JVM启动时,它调用“main”线程上的
main()
方法。在这里面,您使用
SwingUtilities.invokeLater()
,它将启动EDT,您提供的
Runnable
将被执行(在EDT的范围内)。同时,主线程在到达最后一条语句后停止运行。另一方面,EDT从不停止运行并不断等待新事件发生。

在事件调度线程中,您可以看到“事件”一词。这意味着所有(UI)“事件”总是在该特定线程上调度:ActionEvent、PaintEvent、KeyEvent、MouseeEvent等。。。您可以等待多长时间,EDT上将始终发送按钮单击(ActionEvent)


当JVM启动时,它调用“main”线程上的
main()
方法。在这里面,您使用
SwingUtilities.invokeLater()
,它将启动EDT,您提供的
Runnable
将被执行(在EDT的范围内)。同时,主线程在到达最后一条语句后停止运行。另一方面,EDT从不停止运行并不断等待新事件发生。

EDT的范围将持续到事件处理,包括:

  • 由最终用户直接触发的所有事件(鼠标事件、按键事件)以及由这些事件触发的所有高级事件(
    actionListeners
    focusListeners
    等);实际上,您可以说所有的
    AWT
    Swing
    EventListeners
    总是在EDT中调用
  • 所有喷漆代码(当某个区域需要喷漆时,由组件更改或窗口大小或位置更改触发)
  • 或通过
    SwingUtilities.invokeAndWait()或
    SwingUtilities.invokeLater()调用的任何代码

EDT的范围将持续到事件处理,包括:

  • 由最终用户直接触发的所有事件(鼠标事件、按键事件)以及由这些事件触发的所有高级事件(
    actionListeners
    focusListeners
    等);实际上,您可以说所有的
    AWT
    Swing
    EventListeners
    总是在EDT中调用
  • 所有喷漆代码(当某个区域需要喷漆时,由组件更改或窗口大小或位置更改触发)
  • 或通过
    SwingUtilities.invokeAndWait()或
    SwingUtilities.invokeLater()调用的任何代码
  • 默认情况下(我指的是您的代码),创建Swing代码有两点很重要

    • 在EDT上使用并应用LayoutManager(例如
      pack()
      、设置大小等)

    • EDT上容器的setVisible()

    • Swing代码的其余部分对EDT完全不敏感

  • EDT是一个单独的特殊线程,如果从Swing代码初始化,则该线程始终存在于当前JVM中(不活动),并在currnet JVM中过期

    • 默认情况下,来自invokeLater或invokeAndWait(永远看不到使用==我的视图的真正原因)

    • 在所有事件都已完成的情况下,EDT不处于活动状态,然后必须从invokeLater/invokeAndWait(如果EDT处于活动状态,请注意引发的异常)或使用SwingWorker唤醒、激活此线程

  • WorkersThread默认情况下从不调用/激活EDT,Swing GUI不知道从WorkersThreads到GUI的输出,Swing API中方法的事件部分声明为线程安全,这仅在EDT激活的情况下有效,否则不会发生任何事情

  • 在我第一次按下GUI中的任何按钮之前,我等待了很多秒 那么,为什么我的事件处理仍然是在EDT中完成的呢?这不应该吗 是否给EDT足够的时间终止

  • 默认情况下(我指的是您的代码),创建Swing代码有两点很重要

    • 在EDT上使用并应用LayoutManager(例如
      pack()
      、设置大小等)

    • EDT上容器的setVisible()

    • Swing代码的其余部分对EDT完全不敏感

  • EDT是一个单独的特殊线程,如果从Swing代码初始化,则该线程始终存在于当前JVM中(不活动),并在currnet JVM中过期

    • 默认情况下,来自invokeLater或invokeAndWait(永远看不到使用==我的视图的真正原因)

    • 在所有事件都已完成的情况下,EDT不处于活动状态,然后必须从invokeLater/invokeAndWait(如果EDT处于活动状态,请注意引发的异常)或使用SwingWorker唤醒、激活此线程

  • WorkersThread默认情况下从不调用/激活EDT,Swing GUI不知道什么