まず、DefaultTreeModelを使用しないとしましょう。私は自分のTreeModelを実装しているので、DefaultXXXのものを使用できません。問題は次のとおりです。モデルが定義するいくつかのaddStuff()メソッドを使用して、基になるデータ構造にノードを追加します。次に、addStuff()関数内でtreeNodesChanged()を呼び出してリスナーに通知します(treeNodesInsertedメソッドがあることはわかっていますが、同じことです。リスナーに別のメソッドで通知するだけです)。これで、リスナーの1つがメインフォームの静的クラスになり、このリスナーは、メインフォームにも含まれているJTreeにそれ自体を更新するように指示できます。モデルからノードの一部またはすべてを「リロード」するようにJTreeに指示するにはどうすればよいですか?
更新:この質問を見つけました。まったく同じではありませんが、私が望む答えが得られます。
更新2:私の問題は、ビューア(JTree)に通知する方法ではなく、モデルからの通知後にjtreeをどのように再ロードする必要があるかということでした。
まず最初に、基になる変更を反映するためにツリーを更新することを知っている唯一の方法は、updateUI()を呼び出すか、setModel()メソッドを再利用することです。基本的に、私の問題はこれです:
モデルに変更が発生したことがTreeModelListenerに(TreeModelListener APIを介して)通知されたと仮定します。さて、今何?
JTreeがTreeModelListenerを実装していないため、この問題が発生します。したがって、私の状況では、リスナーはJTreeのコンテナー、またはリスナーを実装する内部クラスであり、Jtreeと同じコンテナーの下にあります。
それで、私がTreeModelListenerの実装であり、兄のJTreeと一緒にJFormで幸せに暮らしているとしましょう。突然、私のメソッドtreeNodesInserted(TreeModelEvent evt)が呼び出されました。私は今何をしますか?内部からJtree.updateUI()を呼び出すと、モデルのリスナーリストがConcurrentModification例外をスローします。updateUI以外のものを呼び出すことはできますか?
いろいろ試してみましたが、JTreeを更新したのはupdateUIだけでした。だから私はリスナーの外でそれをしました。JFormから、undrlying構造を変更するモデルのメソッドを呼び出すだけで、次にupdateUIを呼び出します。TreeModelListenerは使用されません。
UPDATE3:暗黙のTreeModelListenersが登録されていることがわかりました。私のモデルのaddTreeModelListener(TreeModelListener listener)実装では、デバッグsystem.out行を配置します。
System.out.println("listener added: " + listener.getClass().getCanonicalName());
jTree.setModel(model)を実行したときに、このデバッグ出力が表示されました。
追加されたリスナー:javax.swing.JTree.TreeModelHandler
追加されたリスナー:javax.swing.plaf.basic.BasicTreeUI.Handler
ConcurrentModificationExceptionは、jtree.updateUI()の呼び出しがリスナー(両方ではなく、plafのみ)を再登録するために発生するため、リスナー通知ループ内でupdateUIを呼び出すとスローされます。ツリーを更新する唯一の方法は、TreeModelListenerの外部で行うことです。より良い解決策についてのコメントやアイデアはありますか?私は何かが足りないのですか?