1

我是摇摆新手,仍在学习它的来龙去脉。我编写了一个基本代码并开始尝试使用 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 足够的时间来终止吗?

提前谢谢!

4

3 回答 3

5

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

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

于 2013-01-08T12:37:05.677 回答
2

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

  • 由最终用户直接触发的所有事件(鼠标事件、按键事件)以及由这些事件触发的所有更高级别的事件(actionListenersfocusListeners...);实际上你可以说 allAWT并且Swing EventListeners总是在EDT中被调用
  • 所有绘画代码(由组件的变化或寡妇大小或位置的变化触发,无论何时需要绘制一个区域)
  • SwingUtilities.invokeAndWait()或通过or调用的任何代码SwingUtilities.invokeLater()
于 2013-01-08T12:39:24.763 回答
1
  1. 默认情况下(我在谈论你的代码)创建 Swing 代码是重要的两点

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

    • EDT 上容器的 setVisible()

    • 其余构建的 Swing 代码对 EDT 完全不敏感

  2. EDT 是一个单独的特殊线程,如果从 Swing 代码初始化,则在当前 JVM 中一直存在(不活动),也与 currnet JVM 过期

    • 默认情况下来自 invokeLater 或 invokeAndWait (永远看不到使用 == 我的观点的真正理由)

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

  3. WorkersThread 默认从不调用/激活 EDT,Swing GUI 不知道从 WorkersThreads 到 GUI 的输出,Swing API 中方法的事件部分被声明为 thread_safe,这仅在 EDT 活动的情况下有效,否则什么都没发生,

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

在 EDT 为空然后返回为 false 的情况下不为真,例如参见

于 2013-01-08T12:46:27.107 回答