首先,让我说我不使用 DefaultTreeModel。我实现了自己的 TreeModel,所以我不能使用 DefaultXXX 的东西。问题是这样的:通过我的模型定义的一些 addStuff() 方法,我将节点添加到底层数据结构中。然后我通过在 addStuff() 函数中调用 treeNodesChanged() 来通知侦听器(我知道有 treeNodesInserted 方法,但它是同一件事。它只是用不同的方法通知侦听器)。现在,其中一个侦听器是我的主窗体中的一个静态类,这个侦听器可以告诉也包含在我的主窗体中的 JTree 刷新自身。如何告诉 JTree 从模型中“重新加载”其部分或全部节点?
更新:发现这个问题虽然不完全相同,但它给出了我想要的答案。
更新2:我的问题不是如何通知查看器(JTree),而是在模型通知后应该以何种方式重新加载jtree。
首先让我说,我知道刷新树以反映底层更改的唯一方法是调用 updateUI(),或重用 setModel() 方法。本质上,我的问题是:
假设 TreeModelListener 刚刚被通知(通过 TreeModelListener API)模型中发生了更改。好的,现在呢?
我有这个问题是因为 JTree 没有实现 TreeModelListener。因此,在我的情况下,侦听器是 JTree 的容器,或者是实现侦听器的内部类,与 Jtree 位于同一容器下。
所以假设我是一个 TreeModelListener 实现,和我的兄弟 JTree 一起快乐地生活在一个 JForm 中。突然我的方法 treeNodesInserted(TreeModelEvent evt) 被调用。现在我该怎么做?如果我从内部调用 Jtree.updateUI(),则模型的侦听器列表会引发 ConcurrentModification 异常。我可以调用 updateUI 以外的其他名称吗?
我尝试了很多东西,但只有 updateUI 刷新了 JTree。所以我在听众之外做了。在 JForm 中,我只调用模型的方法来改变底层结构,然后调用 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 之外进行。对于更好的解决方案有任何意见或想法吗?我错过了什么吗?