Swing TreeModelListener不响应其订阅的TreeModel中的更改

Swing TreeModelListener不响应其订阅的TreeModel中的更改,swing,jtree,defaulttablemodel,Swing,Jtree,Defaulttablemodel,我很难理解为什么我不能让TreeModelChanged侦听器响应它所订阅的模型中的更改 我已经设法在一个小例子中重现了这个问题 每当向树中添加新节点时,SysOut消息不会打印到控制台 我打算用一些命令来替换SysOut消息,以重新绘制树。目前,我使用SysOut消息只是为了证明侦听器没有被解雇 我错过了一些基本的东西吗 import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.Act

我很难理解为什么我不能让TreeModelChanged侦听器响应它所订阅的模型中的更改

我已经设法在一个小例子中重现了这个问题

每当向树中添加新节点时,SysOut消息不会打印到控制台

我打算用一些命令来替换SysOut消息,以重新绘制树。目前,我使用SysOut消息只是为了证明侦听器没有被解雇

我错过了一些基本的东西吗

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;


public class TreeTest {

    private JTree t;
    private DefaultTreeModel m ;

    public static void main(String[] args) {
         new TreeTest();

    }

    public TreeTest() {

        //Draw Frame & Panel  - set dimensions
        JFrame f = new JFrame();
        f.setSize(new Dimension(800,600));
        JPanel p = new JPanel();
        p.setSize(new Dimension(800,600));



        //Create a Tree Model. Give it a String at the root.
        m = new DefaultTreeModel(new DefaultMutableTreeNode("Root"));

        //Create a tree and add the Model to it
        t = new JTree();
        t.setModel(m);


        //Try a Tree Model Listener
        m.addTreeModelListener(new TreeModelListener() {

            private void doSomething() {
                //Should fire whenever a node is added to the model
                System.out.println("Responding to TreeModelListener");
            }
            @Override
            public void treeStructureChanged(TreeModelEvent e) {
                doSomething();

            }

            @Override
            public void treeNodesRemoved(TreeModelEvent e) {
                doSomething();

            }

            @Override
            public void treeNodesInserted(TreeModelEvent e) {
                doSomething();

            }

            @Override
            public void treeNodesChanged(TreeModelEvent e) {
                doSomething();

            }
        });     

        //Add listener to a button which adds nodes to the tree when clicked
        JButton addNode = new JButton("Add node");
        addNode.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("New Node");
                DefaultMutableTreeNode root = (DefaultMutableTreeNode) m.getRoot();
                root.add(newNode);
            }
        });

        JScrollPane s = new JScrollPane(t);


        p.add(s);
        p.add(addNode);

        p.setVisible(true);
        f.add(p);
        f.setVisible(true);
    }

}

那是因为模型不知道加法,它发生在它的脚下。使用DefaultTreeModel上的方法进行插入:

model.insertNodeInto(newNode, root, root.getChildCount())
编辑

树节点只是一个(或多或少)哑数据结构。正如您在api中看到的,它不是可观察的,因此使用该数据结构的模型无法检测节点上是否有任何更改。为了让它意识到变化,你必须做两件事中的一件

  • 使用模型的节点操纵方法
  • 更新节点并手动通知模型(调用NodeWereInserted)

第一种是更好的方法(控制它所属的位置),第二种可能在更复杂的环境中需要(尽管我强烈建议不要这样做,这就是为什么SwingX DefaultTreeTableModel没有公开它们:)

感谢您的建议,这很有效。你能解释一下“发生在它脚下”是什么意思吗?我以为侦听器监视DefaultTreeModel对象的状态变化?我原以为添加像上面代码示例这样的节点就等于这样了?