2011-03-23 96 views
2

我有一系列線程定期檢索RSS源,並希望使用PropertyChangeSupport刷新自定義JTree。然而,它使用實現TreeModel的自定義類,我不知道如何觸發自動更改。這是可能的還是我應該使用另一個班級?更新/刷新TreeModel

回答

3

您必須使用模型的偵聽器集合,並且當您的清爽線程評論一些更改時,您必須將事件觸發給它們。我不認爲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事件,這會導致整個樹重新加載。對於更好的事件,你需要看看事實上發生了什麼變化,然後解決這個問題。

2

不能完全確定,你的意思是「用一個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來簡化這一任務。