JTree не обновляется при вызове в другом месте, но в одной и той же ветке отправки событий - PullRequest
1 голос
/ 21 июля 2011

Я боролся с 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, который я модифицировал, не был правильно добавлен в графический интерфейс, на который я смотрел.

1 Ответ

4 голосов
/ 21 июля 2011

Успокойся .Во-первых, если вы еще этого не сделали, прочитайте учебник Как использовать деревья .Как только вы освоитесь с материалом, вы можете сосредоточить свое внимание на разделе Динамическое изменение дерева .В нем вы найдете пример кода, который, надеюсь, немного прояснит для вас.

Но помните, вы абсолютно правы в том, что пытаетесь сделать.То есть уважайте однопоточную модель Swing.Использование таких механизмов, как SwingUtilities и SwingWorker, для изменения компонента Swing в другом потоке абсолютно правильно, хотя в вашем случае это не представляется возможным.Я думаю, вы просто немного сбиты с толку или перегружены.

...