在“严肃的”Java GUI应用程序中,您将拥有许多GUI元素背后的模型:例如DocumentModel
支持JEditorPane
或背后的ListModel
JList
。
我们总是被告知不要在Swing工作线程外部进行GUI更改,并给出SwingUtilities.invoke...()
来解决这个问题。好吧,我可以忍受!当直接更改GUI组件的属性时,它肯定是必要的(并且运行良好)。
理想情况下,我的大部分GUI可见更改都是模型,而不是JComponents。但是因为它们是GUI可见的,它们是否“算作”GUI变化?即更改事件和监听器是否提供必要的解耦,或者模型更改是否也需要包含在invoke...()
中?
对于Swing专业人士来说可能是老帽子,但是我找不到任何明确说明这种或那种方式的参考文献。
答案 0 :(得分:5)
通常,模型更改必须包装到invokeLater(...)中。在我看到的大多数挥杆类的模型代码中没有解耦。
由您来创建一个模型,该模型可以包含检查在事件调度程序线程上进行GUI修改的调用。
答案 1 :(得分:2)
如果事件是从EDT触发并更新将成为问题的Swing组件。
在Swing文本中,事件可能会也可能不会(!)转移到EDT。这使测试变得棘手。不出所料,API在多线程环境中没用。
所以:最简单的方法是将模型保留在EDT上,其他线程应该传递消息(涉及EventQueue.invokeLater
)。或者你可以在所有东西周围放置一个大锁,这更难(你可能还需要将东西传递给EDT)。尝试进行微同步非常困难。
答案 2 :(得分:2)
是的,这绝对没问题。
虽然确实如此,但您不应修改EDT之外的Swing组件。你当然可以在EDT之外对他们的模型进行更改。
如果您已将模型正确连接到Swing组件,则视图更新和EDT调度几乎会自动发生。
请参阅:http://java.sun.com/products/jfc/tsc/articles/architecture/#roots
请参阅有关JavaBeans事件模型的部分。
这是模型以EDT安全方式将其更改状态传达给GUI的方式。在创建新的GUI组件时,您应该遵循这种设计模式。
还要注意GUI状态模型和应用程序数据模型之间的区别。
从EDT更改模型仍需要小心。事实上,当程序员在EDT中修改模型时,大多数Swing问题都会发生,因为他们应该从一个单独的线程修改它。 (臭名昭着的冻结GUI问题)
此外,这些都不能完全了解典型的多线程陷阱。
但你绝对可以从EDT外部对JTableModel进行更改。