【问题标题】:java.awt.EventQueue.invokeLater explainedjava.awt.EventQueue.invokeLater 解释
【发布时间】:2014-04-27 09:07:03
【问题描述】:

我很好奇为什么要使用java.awt.EventQueue.invokeLater来控制swing组件。

为什么我们不能在普通线程中这样做?幕后究竟发生了什么?从我注意到的情况来看,如果我有JFrame,我可以从主线程将可见性设置为真或假而不会出现任何错误,而且它似乎确实有效。那么使用java.awt.EventQueue.invokeLater 究竟能达到什么目的呢?我也完全知道我可以使用SwingUtilities.invokeLater,但作为explained here,它们似乎是一回事。

感谢任何人的解释。希望这是一个有效的问题。

编辑:回答 wumpz 问题 我们可以创建一个jframe

JFrame frame = new JFrame("Hello world");
frame.setSize(new Dimension(300, 300));
frame.setPreferredSize(new Dimension(300, 300));
frame.setMaximumSize(new Dimension(300, 300));
frame.setMinimumSize(new Dimension(300, 300));
frame.setVisible(true);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

在创建它的同一线程上执行以下操作。

for (int i = 0; i < 34; i++)
{
    System.out.println("Main thread setting to "+(!frame.isVisible()));
    frame.setVisible(!frame.isVisible());
}

没有抱怨。

【问题讨论】:

  • 为什么现在允许在普通线程中执行此操作?有什么例外吗?
  • 它之所以有效,是因为你很幸运——而且众所周知,线程竞赛很难重现。该程序可能看起来可以正常工作,但这并不意味着它没有错误。在 EDT 之外创建和修改组件会破坏线程规则,但破损不一定是可见的。程序越大,在某些系统和某些 java 版本上,它有时开始表现不佳的可能性就越大。
  • @wumpz,阅读 Concurrency 上的 Swing 教程部分以获得更完整的解释。

标签: java swing asynchronous event-handling


【解决方案1】:

完整的 Swing 处理是在一个名为 EDT(事件调度线程) 的线程中完成的。因此,如果您要在此线程中计算一些持久的计算,您将阻止 GUI。

这里的方法是在不同的线程中处理您的计算,以便您的 GUI 保持响应。最后,您想要更新您的 GUI,这必须在 EDT 内完成。现在EventQueue.invokeLater 开始发挥作用。它在 Swings 事件列表的末尾发布一个事件(您的Runnable),并在处理完所有先前的 GUI 事件后进行处理。

这里也可以使用EventQueue.invokeAndWait。不同之处在于,您的计算线程会阻塞,直到您的 GUI 更新。 所以很明显,这不能在 EDT 中使用。

小心不要从不同的线程更新您的 Swing GUI。在大多数情况下,这会产生一些奇怪的更新/刷新问题。

仍然有 Java 代码可以从主线程简单地启动 JFrame。这可能会导致问题,但不会阻止 Swing。大多数现代 IDE 现在创建类似这样的东西来启动 GUI:

public static void main(String args[]) {
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new NewJFrame().setVisible(true);
        }
    });
}

【讨论】:

  • +1 但是 - 不同之处在于, ... 并且必须通过测试 isEventDis.... 从 EDT 中调用,否则会产生一些异常,对 InitialThread 也有效,因为部分方法从 AWT 嵌套创建的 EventQueue
  • 在 java 7 中测试了 invokeLater。没有抛出异常。
  • 关于Also the usage of EventQueue.invokeAndWait is possible here. The difference is ....快手
  • 补充一点我的理解。在最后一个代码 sn-p 中,main 线程可以被视为一种worker thread。只是它向全局EventQueue 发布消息以通知 EDT 启动 GUI,而不是像工作线程通常那样更新 GUI。之后,main 线程退出。但 GUI 将使进程保持活动状态。
  • 所以 AWT 中的 EventQueue.invokeLater 就像 android 中的 handler.post。
【解决方案2】:

所有supported platforms 都提供单线程图形库。 Swing 是跨平台的。因此,Swing GUI 对象应该event dispatch thread 上构造和操作。

顺便说一句,SwingUtilities.invokeLater()EventQueue.invokeLater() 从 1.3 版开始的封面。

【讨论】:

    猜你喜欢
    • 2017-11-23
    • 1970-01-01
    • 2015-03-23
    • 2012-11-12
    • 2012-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多