RSS フィードを定期的に取得する一連のスレッドがあり、PropertyChangeSupport を使用してカスタム JTree を更新したいと考えています。ただし、TreeModel を実装するカスタム クラスを使用しており、自動変更をトリガーする方法がわかりません。これは可能ですか、それとも別のクラスを使用する必要がありますか?
2 に答える
モデルのリスナーのコレクションを使用する必要があり、更新スレッドがいくつかの変更を通知するときに、それらにイベントを発生させる必要があります。PropertyChangeSupport
Treeモデルのデータは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
ルートノードでイベントを発生させることができます。これにより、ツリー全体がリロードされます。より細かいイベントの場合は、実際に何が変更されたかを確認し、これを実行する必要があります。
完全にはわかりませんが、「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があります。