【问题标题】:How to communicate with event dispatch thread or swing components from other threads?如何与事件调度线程或来自其他线程的摆动组件通信?
【发布时间】:2017-02-15 15:26:30
【问题描述】:

我知道 Swing 组件并且应该从事件调度线程调用它们,但到目前为止,我开发了以事件线程为中心的测试应用程序,这意味着 UI 通过在事件调用上调用侦听器来定义程序流。但我读到其他线程不应该与 UI 通信,因为它不同步。

大多数书籍只是教如何使用单个组件,而不是如何使用 在现实世界的应用程序上下文中使用它们。

如何将已完成或正在处理的线程状态更新为摇摆组件。

更新:如果我们将侦听器配置为在ExecutorService 中调用作业,工作线程如何以安全的方式更新 UI 组件。

【问题讨论】:

  • 你可以看看SwingWorker
  • 您不应该从 SwingWorker 内部修改 swing 组件。它们是单独的线程,因此您应该使用“SwingUtilities.invokeLater”
  • @T.G not true : "事件调度线程:所有与 Swing 相关的活动都发生在此线程上。SwingWorker 调用 process 和 done() 方法并通知任何 PropertyChangeListener在这个线程上。” - 来自docs.oracle.com/javase/8/docs/api/javax/swing/SwingWorker.html - 当然你不应该在“doInBackground”中这样做......
  • 是的,你说得对,我应该澄清一下,我的意思是不要修改 doInBackground 中的内容。在大多数情况下,这很诱人,但必须在 EDT 调用的方法中完成。当你必须在后台做某事时,你应该调用 SwingUtilities

标签: java multithreading swing


【解决方案1】:

最安全的方法是使用

SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
            }
        });

在 run 方法中你可以操作 Swing 组件

【讨论】:

    【解决方案2】:

    基本答案是致电repaint

    AWT/Swing 背后的想法是,在任何时候,组件都可以显示、调整大小、移动等(通过代码或通过用户交互)提示需要重新绘制。因此,当您进行更新时,您应该更新渲染将基于的model...有时为了保持一致性而需要在 EDT 上执行此操作,然后使用重绘来显示对模型的更改

    【讨论】:

      【解决方案3】:

      你可以...

      使用SwingUtilities.invokeLater 安排在未来某个时间在 EDT 上执行的回调。

      这样做的问题是在线程之间同步数据,因为更新可能需要的数据可能不再与调用时相同

      你可以...

      使用SwingWorker。这提供了一种在后台线程和 EDT 之间同步数据更改的方法,因为数据被传递到 process 方法,因此它可以在调用时对“相关”/“相关”数据进行操作,这减少了(某些)需要同步访问 UI 可能需要的数据

      更新:如果我们将侦听器配置为在 ExecutorService 中调用作业,工作线程如何以安全的方式更新 UI 组件。

      SwingWorker 本身与ExecutorService 兼容,您可以向其添加SwingWorker 的实例,巧妙的技巧;)

      For example

      【讨论】:

      • 我可以有一个您在此处链接的示例的更简单/新手版本。
      • 你有一个选择,你可以保持原样,永远看不到这个或其他问题的解决方案,或者你可以看看已经链接的相对而言简单的例子,它包括一个完全可运行的示例,您可以运行和调试它,您还可以查看How to use Swing Workers 并学习新知识并成长为开发人员。坦率地说,在线程方面,没有“简单/菜鸟”版本
      【解决方案4】:

      EDT 的唯一工作是调用您的处理程序。您可以与它“通信”的唯一方法是注册处理程序以使其调用。 (注意:invokeLater(...) 方法只是注册 EDT 将立即调用的处理程序的一种方式。)

      我读到其他线程不应该与 UI 通信,因为...

      不要从“沟通”的角度来考虑它。考虑一下在共享对象上运行的线程。你应该说的是,“其他线程不应该对 Swing 对象进行操作。”

      其他线程可以对你的对象进行操作,然后当 EDT 调用它们的 paint(g) 方法时,你的对象可以在屏幕上显示它们的更新状态。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-27
        • 1970-01-01
        • 2017-04-21
        • 2014-07-07
        • 1970-01-01
        相关资源
        最近更新 更多