更新/刷新TreeModel
我有一系列线程定期检索RSS源,并希望使用PropertyChangeSupport刷新自定义JTree。然而,它使用实现TreeModel的自定义类,我不知道如何触发自动更改。这是可能的还是我应该使用另一个班级?更新/刷新TreeModel
您必须使用模型的侦听器集合,并且当您的清爽线程评论一些更改时,您必须将事件触发给它们。我不认为PropertyChangeSupport
会在这里帮助你很多,因为树模型的数据不是以Java bean属性的形式存在的,而且你不想触发PropertyChangeEvents。
TreeModel中实现我做最后一点,我做了这些方法(与德国评论:-P)
/**
* Benachrichtigt die Listener, dass die Struktur unterhalb
* eines bestimmten Knotens komplett geändert wurde.
*/
private void fireStructureChanged(TreePath path) {
TreeModelEvent event = new TreeModelEvent(this, path);
for(TreeModelListener lis : listeners) {
lis.treeStructureChanged(event);
}
}
/**
* Benachrichtigt die Listener, dass unterhalb eines Knotens
* einige Knoten entfernt wurden.
*/
private void fireNodesRemoved(TreePath parentPath,
int[] indices, Object[] nodes) {
TreeModelEvent event =
new TreeModelEvent(this, parentPath, indices, nodes);
for(TreeModelListener lis : listeners) {
lis.treeNodesRemoved(event);
}
}
/**
* Benachrichtigt die Listener, dass ein bestimmter Knoten
* entfernt wurde.
*/
private void fireNodeRemoved(TreePath path, int index, Object node) {
fireNodesRemoved(path, new int[]{index}, new Object[]{node});
}
/**
* Benachrichtigt die Listener, dass sich das Aussehen einiger
* Unterknoten eines Knotens geändert hat.
*/
private void fireNodesChanged(TreePath parentPath,
int[] indices, Object[] nodes) {
TreeModelEvent event =
new TreeModelEvent(this, parentPath, indices, nodes);
for(TreeModelListener lis : listeners) {
lis.treeNodesChanged(event);
}
}
/**
* Benachrichtigt die Listener, dass sich das Aussehen eines Knotens
* geändert hat.
*
* @param parentPath der Pfad des Elternknotens des relevanten Knotens.
* @param index der Index des Knotens unterhalb des Elternknotens.
* Falls < 0, werden die Listener nicht benachrichtigt.
* @param node der Subknoten.
*/
private void fireNodeChanged(TreePath parentPath,
int index, Object node) {
if(index >= 0) {
fireNodesChanged(parentPath, new int[]{index}, new Object[]{node});
}
}
/**
* Benachrichtigt die Listener, dass unterhalb eines Knotens einige
* Knoten eingefügt wurden.
*/
private void fireNodesInserted(TreePath parentPath,
int[] indices, Object[] subNodes) {
TreeModelEvent event =
new TreeModelEvent(this, parentPath, indices, subNodes);
for(TreeModelListener lis : listeners) {
lis.treeNodesInserted(event);
}
}
/**
* Benachrichtigt die Listener, dass ein Knoten eingefügt wurde.
*/
private void fireNodeInserted(TreePath parentPath,
int index, Object node) {
fireNodesInserted(parentPath, new int[]{index}, new Object[]{node});
}
然后从不管什么时候改变了正确的方法是调用模型的其他部分。
如果您想简化一下,您可以简单地始终使用根节点激发一个treeStructureChanged
事件,这会导致整个树重新加载。对于更好的事件,你需要看看事实上发生了什么变化,然后解决这个问题。
不能完全确定,你的意思是“用一个PropertyChangeListener刷新树”,但与保罗认同:一个PropertyChangeListener不有益通知的TreeModel听众(其中包括JTree的)。
这是TreeModel的任何实现通过适当的TreeModelEvents通知其侦听器的内在责任。如果它监听包含节点的变化(可能触发f.i. PropertyChangeEvents),那么它必须将它们转换为TreeModelEvents。
伪代码片段:
public class MyTreeModel implements TreeModel {
PropertyChangeListener nodeListener;
// custom method to insert a node
public void addNodeTo(MyBean child, MyBean parent) {
// ... internal logic to add the new node
fireChildAdded(getPathToRoot(parent), child)
// add a PropertyChangeListener to new node so the model
// can comply to its notification contract
child.addPropertyChangeListener(getPropertyChangeListener();
}
protected void nodePropertyChanged(MyBean bean) {
firePathChanged(getPathToRoot(bean));
}
protected TreePath getPathToRoot(MyBean bean) {
// construct and return a treePath to the root
}
protected PropertyChangeListener getPropertyChangeListener() {
if (nodeListener == null) {
nodeListener = new PropertyChangeChangeListener() {
public void propertyChanged(...) {
nodeChanged((MyBean) e.getSource();
}
);
}
}
构建真实事件是一个有点混乱(且不良记录),这就是为什么SwingX has a helper class TreeModelSupport来简化这一任务。