我一直在与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在添加节点后无法自行刷新。我尝试了几种方法将它放在Event-Dispatching Thread上,但它不起作用。我也在主线程上尝试过,它也失败了。代码示例如下:
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
的一些最佳实践?
更新:问题解决了。它实际上与JTrees无关。我正在修改的JTree实例未正确添加到我正在查看的GUI中。
答案 0 :(得分:4)
安顿下来。首先,如果您还没有,请阅读How to Use Trees教程。一旦您对材料感到满意,就可以将注意力集中在Dynamically Changing a Tree分区上。在那里你会找到样本代码,希望能让你的内容更加清晰。
但请记住,你在做什么的时候是完全正确的。也就是说,尊重Swing的单线程模型。使用SwingUtilities
和SwingWorker
等机制在另一个线程中修改Swing组件是绝对正确的,尽管这似乎不适用于您的情况。我认为你只是有点误导,或者不堪重负。