2

RSS フィードを定期的に取得する一連のスレッドがあり、PropertyChangeSupport を使用してカスタム JTree を更新したいと考えています。ただし、TreeModel を実装するカスタム クラスを使用しており、自動変更をトリガーする方法がわかりません。これは可能ですか、それとも別のクラスを使用する必要がありますか?

4

2 に答える 2

3

モデルのリスナーのコレクションを使用する必要があり、更新スレッドがいくつかの変更を通知するときに、それらにイベントを発生させる必要があります。PropertyChangeSupportTreeモデルのデータはJavaBeansプロパティの形式ではなく、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ルートノードでイベントを発生させることができます。これにより、ツリー全体がリロードされます。より細かいイベントの場合は、実際に何が変更されたかを確認し、これを実行する必要があります。

于 2011-03-23T23:48:32.700 に答える
2

完全にはわかりませんが、「PropertyChangeListenerを使用してツリーを更新する」とはどういう意味ですか。ただし、Paulに同意します。PropertyChangeListenerは、treeModelリスナー(JTreeを含む)に通知するのに役立ちません。

適切なTreeModelEventsを使用してリスナーに通知することは、TreeModelの実装の本質的な責任です。含まれているノードの変更(fi 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にはそのタスクを簡素化するためのヘルパークラスTreeModelSupportがあります。

于 2012-02-16T12:07:58.730 に答える