Обновление / обновление TreeModel - PullRequest
2 голосов
/ 24 марта 2011

У меня есть серия потоков, регулярно получающих RSS-каналы, и я хочу обновить пользовательское JTree с помощью PropertyChangeSupport.Однако он использует собственный класс, реализующий TreeModel, и я не уверен, как вызвать автоматическое изменение.Это возможно, или я должен использовать другой класс?

Ответы [ 2 ]

3 голосов
/ 24 марта 2011

Вам нужно будет использовать набор слушателей вашей модели, и когда ваш обновляющий поток отмечает некоторые изменения, вам придется запускать события для них. Я не думаю, что PropertyChangeSupport сильно вам здесь поможет, поскольку данные модели дерева представлены не в форме свойств Java-бинов, и вы не хотите запускать 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 голосов
/ 16 февраля 2012

Не совсем уверен, что вы подразумеваете под "обновить дерево с помощью 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 имеет вспомогательный класс TreeModelSupport для упрощения этой задачи.

...