3

我有一个关于使用 SwingUtilities 的 invokeLater 方法的正确做法的问题。

所以首先,我想确认我理解正确。

据我了解,必须在 EDT 上更改 GUI,因为 Swing 组件不是线程安全的。invokeLater 方法将 Runnable 作为参数,并且该 runnable 中包含的任何内容都将在 EDT 上运行。因此,对 Swing 组件的任何调用都被放入一种队列中,在 EDT 上一次执行一个。

有了这个,我的问题是:使用它的好习惯是什么?据我所知,至少有两种方法可以做到:

1) 在main方法中,将所有代码,例如 GUI 创建、Controller 创建,甚至 Model 创建(假设为 MVC 类型模式),放在由 invokeLater 方法调用的 Runnable 中。当然,这是假设模型中任何长时间运行的任务都将使用 SwingWorker 执行。

2)将GUI创建放在invokeLater中,而将Controller创建和Model创建放在main方法中。然后,每当您需要从 Controller 访问 Swing 组件时,您可以在 invokeLater 方法中弹出所述代码,将其放置在 EDT 队列中。

这两个中的哪一个被认为是最佳实践或坏实践?如果这两个都不好,那么更好的方法是什么?

任何信息将不胜感激。

谢谢。

4

2 回答 2

1

SwingWorker 并不特别,它只是一些常见场景的封装。它将代表您调用 invokeLater,因此您提出的两种情况实际上只是同一事物的实例。

只需确保遵循以下两条规则: 1. 不要停止 EDT 2. 在 EDT 上执行 Swing 相关代码

于 2020-06-05T05:16:43.413 回答
1

这确实是一个有趣的问题,而公认的答案并没有完全回应它。

您建议的两种方法都可以接受并且可以正常工作,但我相信第一种方法比第二种方法更好(在 EDT 上全部执行,如果有一些长时间运行的任务在 SwingWorker 或新线程上执行如果它们与 Swing 无关)。


为什么?正如@ThomasKrägler 在这里指出的那样:

虽然您可以在主线程和 EDT 之间拆分这些任务(模型、控制器和视图创建)(并且可能会在 UI 首次显示之前获得几毫秒),但它也会使应用程序的设计复杂化(多线程不是一个简单的话题)和使用 invokeLater() 调用乱扔代码库。

考虑到 EDT 在模型和控制器初始化之前不需要处理任何东西(因此也启动了视图)。所以你可以使用 EDT 来初始化它们,因为它不会对你的 UI 产生任何负面影响(目前还没有 UI)。

这样做,您将节省很多invokeLater电话和可能的错误忘记调用invokeLater。你的代码也会看起来更干净。

于 2021-03-17T11:33:38.297 回答