确定事件调度线程的范围

时间:2013-01-08 12:31:57

标签: 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.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

似乎我一直在美国东部时间。我的问题是,jfr.setVisible(true)语句不应该SwingDemo2()构造函数返回main()而不应该是EDT的结束?

在我第一次按下GUI中的任何按钮之前,我等了好几秒钟,为什么我的事件处理仍在EDT中完成?难道不应该让EDT有足够的时间来终止吗?

提前Thanx!

3 个答案:

答案 0 :(得分:5)

在事件调度线程中,您会看到“事件”一词。这意味着所有(UI)“事件”总是在该特定线程上调度:ActionEvent,PaintEvent,KeyEvent,MouseEvent等...您可以等待所需的时间,将始终调度按钮单击(ActionEvent)美国东部时间。

当JVM启动时,它会调用“Main”-Thread上的main()方法。在其中,您使用将启动EDT的SwingUtilities.invokeLater()并且将执行您提供的Runnable(在EDT的范围内)。与此同时,您的主线程在到达其最后一个语句后停止运行。另一方面,EDT永远不会停止运行并不断等待新事件的发生。

答案 1 :(得分:2)

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

  • 最终用户直接触发的所有事件(鼠标事件,关键事件)以及由这些事件触发的所有更高级别事件(actionListenersfocusListeners等... );实际上你可以说所有AWTSwing EventListeners总是在 EDT
  • 中调用
  • 所有绘画代码(由组件变化或寡妇大小或位置变化触发,当需要绘制区域时)
  • 或通过SwingUtilities.invokeAndWait()SwingUtilities.invokeLater()调用的任何代码。

答案 2 :(得分:2)

  1. 默认情况下(我说的是你的代码)创建Swing代码是重要的两点

    • 在EDT上使用并应用LayoutManager(例如pack(),setSize等...)

    • EDT上容器的setVisible()

    • 其余构建的Swing代码根本不是EDT敏感的

  2. EDT是一个特殊的线程,它在当前的JVM中始终存在(不存在),如果从Swing Code中初始化,也会被currnet JVM过期

    • 默认情况下来自invokeLater或invokeAndWait(永远不会看到使用的真实原因==我的观点)

    • 在所有事件都完成的情况下,EDT不活动,然后必须唤醒,从invokeLater / invokeAndWait激活此线程(如果EDT处于活动状态则通知导致异常)或使用SwingWorker

      < / LI>
  3. WorkersThread默认情况下永远不会调用/生成EDT,Swing GUI不知道从WorkersThreads到GUI的输出,Swing API中的方法的事件部分被声明为thread_safe,这只适用于这种情况EDT还活着,否则没什么事情发生,

  4.   

    在我第一次按下GUI中的任何按钮之前,我等了好几秒钟   那么为什么我的事件处理仍然在EDT完成?不应该那样   给了EDT足够的时间终止?,

  5. not true in the case that EDT is empty then returns is false, see for example