Я боролся с JTree
.Я не могу обновить его после добавления нового узла дерева (DefaultMutableTreeNode
).Я могу обновить его, когда код, который добавляет узел дерева, называется изнутри класса GUI, но не снаружи.Вот код, который фактически добавляет узел к JTree
:
public class TreeViewer extends JPanel implements TreeSelectionListener {
JTree tree;
DefaultMutableTreeNode rootNode;
DefaultTreeModel treeModel;
public void modifyJTree(String name) {
DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(name);
treeModel.insertNodeInto(childNode, rootNode, rootNode.getChildCount());
}
}
Когда он вызывается в методе main, GUI не смог обновить себя после добавления узла.Я экспериментировал с несколькими способами поместить его в поток событий, но он не работает.Я также попробовал это в главном потоке, и это также не удалось.Ниже приведены примеры кода:
public static void main(String[] args) throws Exception {
final TreeViewer viewer = new CaseViewer();
// I omit the code that sets up the GUI and displays it
// This calls modifyJTree on the Event-Dispatching Thread
// And it does not work
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
viewer.modifyJTree("InvokeLater");
}
});
// This also calls modifyJTree on the Event-Dispatching Thread
// And it still does not work
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
viewer.modifyJTree("InvokeLater");
}
});
// Using a SwingWorker. Still no luck.
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
Thread.sleep(5000);
return null;
}
@Override
protected void done() {
viewer.modifyJTree("SwingerWorker");
}
};
// Now I tried to call it on the main thread, but this cannot work
viewer.modifyJTree("main thread");
}
Однако, если вызов выполняется внутри класса, он работает.Например, в конструкторе моего TreeViewer
класса, как показано ниже:
public TreeViewer() {
rootNode = new DefaultMutableTreeNode("Root Node");
treeModel = new DefaultTreeModel(rootNode);
treeModel.addTreeModelListener(new MyTreeModelListener());
tree = new JTree(treeModel);
tree.setEditable(false);
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setShowsRootHandles(true);
// Listen for when the selection changes.
tree.addTreeSelectionListener(this);
// omitting other initialization stuff
// Using a SwingWorker. It is the same SwingWorker, but this one works!
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
Thread.sleep(5000);
return null;
}
@Override
protected void done() {
viewer.modifyJTree("InsideSwingerWorker");
}
};
}
Поэтому у меня сложилось впечатление, что вызов должен исходить из класса TreeViewer
.Однако, если метод не может быть вызван извне класса, мой TreeViewer
в основном бесполезен.Я не могу помочь, но подозреваю, что это ошибка JVM
.Или я не в курсе некоторых рекомендаций, касающихся JTree
s, которые вызвали эту странную ошибку?
Обновление : проблема решена.Это на самом деле не имеет ничего общего с JTrees.Экземпляр JTree, который я модифицировал, не был правильно добавлен в графический интерфейс, на который я смотрел.