【问题标题】:Updating/refreshing a TreeModel更新/刷新 TreeModel
【发布时间】:2011-07-21 17:48:09
【问题描述】:

我有一系列线程定期检索 RSS 提要,并希望使用 PropertyChangeSupport 刷新自定义 JTree。但是它使用实现 TreeModel 的自定义类,我不确定如何触发自动更改。这是可能的还是我应该使用另一个类?

【问题讨论】:

    标签: java swing treemodel


    【解决方案1】:

    您必须使用模型的一组侦听器,并且当您的刷新线程注意到一些更改时,您必须向它们触发事件。我认为PropertyChangeSupport 不会对您有太大帮助,因为 Tree 模型的数据不是 Java bean 属性的形式,而且您不想触发 PropertyChangeEvents。

    在我最后做的 TreeModel 实现中,我制作了这些方法(使用德国 cmets :-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 刷新树”是什么意思,但同意 Paul 的观点:PropertyChangeListener 在通知 treeModel 侦听器(包括 JTree)方面没有帮助。

      通过适当的 TreeModelEvents 通知其侦听器是 TreeModel 的任何实现的内在责任。如果它侦听包含节点的更改(可能会触发 f.i. PropertyChangeEvents),那么它必须将这些转换为 TreeModelEvents。

      一个伪代码sn-p:

      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 简化该任务的原因。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-19
        • 2012-10-25
        • 2012-05-04
        • 2014-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多