TreeModellistener не отвечает на изменения в TreeModel, на которые он подписывается на
-
26-10-2019 - |
Вопрос
У меня есть некоторое беспокойство, почему я не могу заставить слушателя 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())
Редактировать
TreeNode - это просто (более или менее) глупая структура данных. Как вы можете видеть в API, он не наблюдается, так что есть ни за что Для модели, которая использует эту структуру данных для обнаружения, если что -то изменилось на узле. Чтобы понять об этом изменении, вы должны сделать одну из двух вещей
- Используйте методы манипуляции с узлом модели
- Обновите узел и уведомите модель вручную (вызов Nodeswereinserted)
Во -первых, это предпочтительный способ (сохраняет контроль там, где он находится), второй может понадобиться в более сложных контекстах (хотя я настоятельно рекомендую никогда Сделай это, вот почему Swingx DefaultTreetableModel их не открывает :)