在不同位置调用JTree时不刷新但在同一事件调度线程上

时间:2011-07-20 23:33:48

标签: java swing jtree

我一直在与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中。

1 个答案:

答案 0 :(得分:4)

安顿下来。首先,如果您还没有,请阅读How to Use Trees教程。一旦您对材料感到满意,就可以将注意力集中在Dynamically Changing a Tree分区上。在那里你会找到样本代码,希望能让你的内容更加清晰。

但请记住,你在做什么的时候是完全正确的。也就是说,尊重Swing的单线程模型。使用SwingUtilitiesSwingWorker等机制在另一个线程中修改Swing组件是绝对正确的,尽管这似乎不适用于您的情况。我认为你只是有点误导,或者不堪重负。