Java 当使用PropertyChangeListener和DocumentListener绑定模型和GUI时,如何避免竞争条件?

Java 当使用PropertyChangeListener和DocumentListener绑定模型和GUI时,如何避免竞争条件?,java,swing,user-interface,data-binding,Java,Swing,User Interface,Data Binding,我想将Java Swing JTextField绑定到数据模型的字符串属性 因此,我想使用一个PropertyChangeListener,它侦听模型中文本属性的更改,然后更新GUI(模型-->GUI)中的文本字段 对于另一个方向(GUI-->模型),我想在JTextField的文档上使用DocumentListener,当用户更改字段中的文本时,它应该更新模型 当我这样做时,只要我更改文本字段中的文本,就会得到一个非法状态异常 java.lang.IllegalStateException:

我想将Java Swing JTextField绑定到数据模型的字符串属性

因此,我想使用一个PropertyChangeListener,它侦听模型中文本属性的更改,然后更新GUI(模型-->GUI)中的文本字段

对于另一个方向(GUI-->模型),我想在JTextField的文档上使用DocumentListener,当用户更改字段中的文本时,它应该更新模型

当我这样做时,只要我更改文本字段中的文本,就会得到一个非法状态异常

java.lang.IllegalStateException: Attempt to mutate in notification
  at javax.swing.text.AbstractDocument.writeLock(AbstractDocument.java:1323)
  at javax.swing.text.AbstractDocument.replace(AbstractDocument.java:644)
  at javax.swing.text.JTextComponent.setText(JTextComponent.java:1693)
      ...
我怎样才能避免这种情况

顺便说一句:
BeansBinding对我来说并不是一个真正的统计解决方案,因为它已经被放弃了,而且我必须先实例化对象图中的一些对象,然后才能写入它们。

这个问题以前已经讨论过:


简而言之,文档监听器不应该修改文档的内容。

好吧,可能一个难看的解决方法是使用SwingUtilities.invokeLater()将GUI更新延迟到通知之外

然而,我认为立即将二级模型对象与GUI同步的整个方法是有缺陷的。GUI有自己的模型(TextField使用的文档)。或者您的模型应该实现它,然后您不需要做任何特殊的事情(然后您的模型对象将替换普通文档作为模型)


或者,您可以选择一个适当的点来同步GUI和数据模型。通常,当窗口/对话框打开时,以及当用户单击“确定/保存”时,都是一个好时机。如果您立即同步模型,您将如何实现“取消”?

这不是竞争条件,因为所有事情都发生在同一个线程上。问题是,正如异常所说:“尝试更改文本,同时通知侦听器文本已更改”

因为在此场景中,您试图用相同的文本替换文本,所以您可以跳过属性更改侦听器中的更新:

if(!modelText.equals(textField.getText())) {
  textField.setText(modelText);
}

您的
PropertyChangeListener
是否正在从事件调度线程更新文本字段?你能发布一些代码吗?是的,它正在启动EDT的更新。如果我将SwingUtilities.invokeLater(…)添加到DocumentListener,一切都会正常工作。缺点是在我的代码中有很多可伸缩性和可运行性。也许有一个更优雅的解决方案……我已经通过让我的数据模型实现UndoableEditSupport实现了“取消”。当用户打开对话框时,我注册了UndoManager的一个新实例,如果它单击“确定”,UndoManager将被丢弃,如果单击“取消”,我将对UndoManager中的所有操作调用undo。我的想法是使用上面描述的PropertyChangeListeners和DocumentListeners组合将数据模型的所有属性“绑定”到gui。我觉得这听起来太过工程化了,但是你可能会使用“用你自己的模型替换TextField模型”的方法,它应该适合你的架构。因此,如果我理解正确,您建议在GUI进入屏幕时手动将其与模型同步,然后在用户单击“确定”检查是否有修改并将其写回(如果有修改的话)?关于如何处理这种情况,有没有默认的方法?遗憾的是,似乎没有绑定模型/GUI的标准方法。GUI框架通常将问题留给应用程序,就像另一方的ORM一样。我从未见过一个简单而灵活的解决方案。关于“即时”同步,问问你自己:它以什么代价为你带来了什么?仅仅因为我认为它的过度设计并不一定意味着它是-我不知道你的具体需求。你可能想看看中提到的数据绑定框架(我没有使用过任何一个,所以我不能对它们发表评论)。哦,这听起来很简单。我明天就试试。