【问题标题】:eli5 swing worker and swing threadeli5 swing worker 和 swing thread
【发布时间】:2013-11-28 17:47:44
【问题描述】:

我有一个程序,我从这里 (how do I make my program check the stock market value every hour[java]) 得到了一些帮助,从那时起我就一直在阅读关于摇摆工人的文章。我仍然没有修复程序,因为我重读了 3 次官方文档,我仍然有点困惑。这是我认为我理解的内容,如果我错了,请纠正我。

当你有一个很长的后台进程时你使用 SwingWorker,你把 SwingWorker 放在你执行的操作中?一旦你创建了你的进程,如果你想让它更新 GUI,你让它返回一个值,然后你从 SwingWorker 的 done() 方法中 get() 值。我对“在哪里”初始化 SwingWorker 感到困惑,因为我想说它执行的操作,但这不就是 SwingInvokeLater 所涉及的地方吗?如果是这样的话,那么两者之间有什么区别。我相信 SwingInvokeLater 和 done() 都通过在 EDT 上运行来更新您的 GUI。

把这些都写出来我感觉很迷茫,我觉得我越来越接近理解了,但由于某种原因它只是不会点击。我不喜欢官方文档提供的示例,我想我只是没有看到全貌。官方文档说要在 SwingInvokeLater 中初始化你的 GUI,但我不明白这与在 main() 中初始化我的 GUI 之间的区别。

【问题讨论】:

    标签: java swing


    【解决方案1】:

    您的问题/我的回复:

    当你有一个长的后台进程时你使用 SwingWorker,你把 SwingWorker 放在你执行的操作中?

    它可以进入 ActionListener 内部,是的。您创建它并在需要的地方执行它,不多也不少。

    一旦你创建了你的进程,如果你希望它更新 GUI,你让它返回一个值,然后你从 SwingWorker 的 done() 方法中 get() 值。

    这是更新 GUI 的一种方法。您还可以使用发布/处理方法对来使用中间结果更新 GUI。您还可以使用附加到 SwingWorker 的 PropertyChangeListener 来更新 GUI。无论如何,在某个地方调用get() 通常是个好主意,即使没有返回任何内容,因为这将使您的 Swing GUI 能够意识到在 SwingWorker 运行期间可能引发的任何异常。

    我很困惑“在哪里”初始化 SwingWorker,因为我想说它执行的操作,但这不就是 SwingInvokeLater 所涉及的地方吗?

    SwingUtilities.invokeLater(...) 用于将代码排队到 Swing 事件线程,即 EDT。这在 ActionListener 内部不是必需的,因为它的代码已经在 Swing 事件线程上调用。

    如果是这样的话,两者之间的区别是什么。

    它们完全不同。同样,invokeLater(...) 用于调用事件线程上的代码,而 SwingWorker 用于从事件线程中调用长时间运行的代码。

    我相信 SwingInvokeLater 和 done() 都通过在 EDT 上运行来更新您的 GUI。

    是的,他们都可以。

    官方文档说要在 SwingInvokeLater 中初始化你的 GUI,但我不明白这与在 main() 中初始化我的 GUI 之间的区别。

    通过使用SwingUtilities.invokeLater(...),您可以保证传递给它的代码在 EDT(事件调度线程)上运行。如果你不这样做,你就没有这个保证。虽然许多 Swing 程序大部分时间都会在不这样做的情况下运行,但如果不注意这一点,它们可能(并且确实)有时会失败。


    编辑

    所以我想我正朝着正确的方向前进。如果我有一个在网站上每小时检查一个值的过程,因为它的过程很短(需要一秒钟),使用 invokeLater() 会更好吗?

    您可以为此使用某种类型的计时器,可能是在 Swing 后台运行的 ScheduledExecutorService,也可能与 SwingWorker 一起运行。然后该进程将被称为 Swing 线程的后台,您可以通过发布/进程更新 GUI。

    整个代码块是放在invokeLater 中还是只是更新GUI 部分。我觉得整个代码应该放在invokeLater中,但有人告诉我只是在invokeLater()中更新GUI,例如(text.setText())。

    如前所述,您的 GUI 需要在 Runnable 内启动,该 Runnable 被传递到对 invokeLater(...) 的调用中。至于程序运行时,如果后台代码使用 SwingWorker 运行,则通常不需要调用 invokeLater(...)。这就是使用 SwingWorker 而不是普通的普通线程的原因之一。


    编辑 2
    你说:

    我刚刚在测试时遇到的最后一个问题..在执行的操作中,我让 buttonclick 更改文本字段以打招呼,然后我为 Thread.sleep(1000) 设置了 try catch,然后将文本字段更改为打招呼。为什么结果只输出 ho?它不显示嗨,我用数字测试过,可以看到程序锁定。我知道使用线程可以解决这个问题,但只是想知道为什么如果我休眠它不会显示输出。

    当您调用 Thread.sleep(...) 时,您将调用线程(此处为 Swing 事件调度线程或 EDT)休眠。由于它负责所有 Swing 绘制和用户交互,因此整个应用程序进入休眠状态,并且 GUI 在休眠完成之前无法执行任何更新。这正是您必须使用后台线程来执行此类事情的原因。

    【讨论】:

    • 感谢您的回答,它帮助了很多。所以我想我正朝着正确的方向前进。如果我有一个在网站上每小时检查一个值的过程,因为它的过程很短(需要一秒钟),使用 invokeLater() 会更好吗?整个代码块是否进入 invokeLater 或只是更新 GUI 部分。我觉得整个代码应该放在invokeLater中,但有人告诉我只是在invokeLater()中更新GUI,例如(text.setText())。
    • 我刚刚在测试时遇到的最后一个问题..在执行的操作中,我让 buttonclick 更改文本字段打招呼,然后我为 Thread.sleep(1000) 设置了一个 try catch 然后更改文本字段说嗬。为什么结果只输出 ho?它不显示嗨,我用数字测试过,可以看到程序锁定。我知道使用线程可以解决这个问题,但只是想知道为什么如果我休眠它不会显示输出。
    • @droidbehavior:请参阅编辑 2 来回答。
    猜你喜欢
    • 2012-05-29
    • 1970-01-01
    • 1970-01-01
    • 2013-05-28
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    • 2012-12-10
    • 2015-01-06
    相关资源
    最近更新 更多