2

Java Swing JTextField をデータ モデルの String 属性にバインドしたいと考えています。

したがって、モデルのテキスト属性の変更をリッスンし、GUI (モデル->GUI) のテキストフィールドを更新するPropertyChangeListenerを使用したいと考えています。

もう一方の方向 (GUI->モデル)では、ユーザーがフィールド内のテキストを変更したときにモデルを更新する必要がある JTextField のドキュメントでDocumentListenerを使用したいと考えています。

そうすると、テキストフィールドのテキストを変更するとすぐにIllegalStateExceptionが発生します。

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 は、放棄されているため、実際には統計的な解決策ではありません。さらに、オブジェクトに書き込む前に、オブジェクトグラフでいくつかのオブジェクトをインスタンス化する必要があります。

4

3 に答える 3

4

すべてが同じスレッドで発生するため、競合状態ではありません。問題は、例外が言うように、「テキストが変更されたことをリスナーに通知しながらテキストを変更しようとする」ことです。

このシナリオでは、テキストを同じテキストに置き換えようとしているため、プロパティ変更リスナーで更新をスキップできます。

if(!modelText.equals(textField.getText())) {
  textField.setText(modelText);
}
于 2012-07-31T15:29:29.073 に答える
2

この問題は以前に取り上げられています: https://stackoverflow.com/a/2789307/474189

つまり、ドキュメント リスナはドキュメントの内容を変更してはなりません。

于 2012-07-31T14:47:29.943 に答える
2

まあ、おそらく厄介な回避策は、SwingUtilities.invokeLater() を使用して GUI の更新を通知の外に延期することです。

しかし、第 2 レベルのモデル オブジェクトを GUI と即座に同期させるという全体的なアプローチには欠陥があると思います。GUI には独自のモデル (TextField が使用するドキュメント) があります。モデルがそれを実装する必要がある場合は、特別なことをする必要はありません (その後、モデル オブジェクトが通常の Document as model を置き換えます)。

または、GUI とデータ モデルを同期する適切なポイントを決定します。通常、適切なポイントは、ウィンドウ/ダイアログが開いたとき、およびユーザーが [OK]/[保存] をクリックしたときです。モデルを即座に同期する場合、「キャンセル」をどのように実装しますか?

于 2012-07-31T14:47:57.367 に答える