【问题标题】:Determining scope of Event Dispatch Thread确定事件调度线程的范围
【发布时间】:2013-01-08 12:31:56
【问题描述】:

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

提前谢谢!

【问题讨论】:

  • 试着在invokeLater()之外写一个isEventDispatchThread(),在你的main方法中,你会明白他们是多么的分开。当 Swing 应用程序运行时,会启动三个线程。 1。主线程: 您的应用程序从该线程运行。 2。工具包线程: 该线程负责捕获系统事件,例如键盘按键或鼠标移动。虽然,这个线程从不运行应用程序代码。捕获的事件被传递到第三个线程,即 EDT。 3。 EDT - Event Dispatch Thread: 负责调度工具包线程捕获的事件。
  • EDT 是您与 Swing 交互的线程。
  • @GagandeepBali 另一个愚蠢的问题: Swing 应用程序有多少个 EDT?当我尝试在已经存在的之后调用invokeLater 再次时,程序编译并运行完美。它是在同一个 EDT 中运行还是创建了一个新的?
  • No invokeLater() 实际上是用来将你的新任务放在同一个EDT 上。还有一种称为invokeAndWait() 的方法,尽管它会将任务放在EDT 上,并等到该任务未完成。因此它会在这段时间内阻塞EDT,直到任务没有完成。这个使用起来有点棘手,因为如果使用不当,它可能会导致deadlocks/run conditions
  • 每当创建新任务时,您只需使用invokeLater() 将该任务放在EDT queue 上,它根据FIFO AFAIK 原则执行任务。

标签: java multithreading swing event-handling event-dispatch-thread


【解决方案1】:

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

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

【讨论】:

  • 也就是说EDT不像普通线程?只要 GUI 正在运行,它就永远不会终止?
  • @SurenderThakran 是的,准确地说。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:
    1. 默认情况下(我说的是你的代码)创建 Swing 代码是重要的两点

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

      • setVisible() 用于 EDT 上的容器

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

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

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2015-11-06
      • 2011-11-11
      • 2011-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多