当我第一次看到 javax.swing.tree.TreeModel
时,我认为编写所有方法的工作量相当大。然后我找到了 DefaultTreeModel
并认为它可以很容易地通过适配器模式用于文件树。所以我开始编写适配器,但有点失败。我需要能够访问给定 TreeNode
的相应文件(这很容易,因为它可以是一个实例变量),但我也需要反过来。这可以使用 Map 来解决,但它占用了大量内存。切换到 WeakHashMap
有所帮助。
这行得通,但是当树改变时我遇到了一些奇怪的问题。此外,由于 File.list()
被多次调用,这一切都非常缓慢。有多个愚蠢的方法,如 getChildCount()
、getChild(Object parent, int index)
和 getIndexOfChild(Object parent, Object child)
和在我天真的实现中,每次调用都会导致读取一个目录。
这一切都是相当多的工作,结果很糟糕。当然,这是我的错,但这不是使用有缺陷的过于复杂的模型的直接后果吗?
如果只有一个像 List getChildren(Object)
这样的方法,就不会发生这种情况。也许我做错了,正确的方法是什么?
最后,我使用 per class 适配器编写了 MyCachingTreeModel implements TreeModel
,这解决了所有问题。但我仍然很好奇它还能如何解决。
更新:
以上内容可能看起来像是一种咆哮,而不是一个正确的问题。所以我再试一次:
如何有效地为文件系统树实现 TreeModel,以便它显示目录的当前状态?
我的解决方案在这里不算数,因为我绕过了整个模型。此外,它缓存太多,几乎不会注意到任何变化。
最佳答案
(很晚的编辑:)
How to implement a TreeModel for the filesystem tree efficiently so that it shows the current state of the directories?
我认为没有一种真正好的方法可以用 JTree 显示目录树,因此它始终是最新的。
问题在于模型必须在重要更改发生时通知其监听器(= JTree),而这只有在我们定期重新检查文件时才有可能。所以你的模型至少需要一个自己的线程。自然地,它应该只检查那些节点实际显示的文件——但模型并不知道这一点(只能通过最后一次调用 getValue()
来猜测)。
也许可以将此与缓存问题结合起来:拥有一个与最后查询的节点相对应的目录对象的缓存,以及“最后检查”的时间。在第一次创建后的一段时间内,它们仍然有效,我们缓存子文件列表,但稍后将它们丢弃。对于树查询的这些相同对象,我们也会在一段时间后再次查看文件系统,并在与以前不同时触发正确的更改事件。
这仍然依赖于很多启发式方法来了解必须检查哪些文件 - 也许我们应该打破分层,让我们的模型简单地询问树显示哪些节点,只重新检查(和缓存)那些。
(旧的不是真正的答案:)
创建 TreeModel API 时(与整个 Swing 同时创建),集合框架还不存在。这也是我们在 Swing 中的多个地方需要一个 Vector(而不是 List)的原因。
关于java - TreeModel 真的有我想的那么糟糕吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4901102/