JTree model.nodechanged(Node)丢失数据 [英] JTree model.nodechanged(Node) loses data

查看:155
本文介绍了JTree model.nodechanged(Node)丢失数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用JTree测试一些代码,并且我注意到model.reload()提供的输出与model.nodeChanged(currentNode)不同.从model.reload()获得正确的输出.这是我针对相同代码的两个输出:

I am testing some code with JTree, and I noticed that model.reload() gives different output than model.nodeChanged(currentNode). The correct output is obtained from model.reload(). Here are my two outputs for the same code:

我的代码如下:

public class test {

    private JFrame frame;
    JTree tree;
    DefaultMutableTreeNode root;
    DefaultTreeModel model;
    private Map<String, DefaultMutableTreeNode> treeMap;

    public static void main(String[] args) {
        test t = new test();
        try {
            Thread.sleep(1000 * 5);
        } catch (Exception e) {

        }
        t.add_new_folder("Data", "trial 0");
        t.add_new_folder("Data/trial 0", "trial 1");
        t.add_new_folder("Data/trial 0/trial 1", "trial 2");
        t.add_new_folder("Data", "trial 1");

        try {
            Thread.sleep(1000 * 5);
        } catch (Exception e) {

        }
        t.add_new_folder("Data/trial 1", "trial 2");
        t.add_new_folder("Data", "trial 2");
    }

    public test() {
        frame = new JFrame("using reload");
        tree = new JTree();
        root = new DefaultMutableTreeNode("Data");
        model = new DefaultTreeModel(root);
        tree.setModel(model);
        frame.getContentPane().add(tree, BorderLayout.WEST);
        frame.setVisible(true);
        frame.setSize(500, 500);
        treeMap = new HashMap<>();
        treeMap.put("Data", root);
    }

    public void add_new_folder(String path, String name) {
        DefaultMutableTreeNode currentNode = treeMap.get(path);
        DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(name);
        currentNode.add(childNode);
        treeMap.put(path + "/" + name, childNode);
        model.reload();
        //model.nodeChanged(currentNode);
    }
}

我还需要使用model.nodeChanged(),因为它使扩展路径与model.reload不同.有什么解释以及如何解决?

I need also to use model.nodeChanged() as it keeps expanded paths the same unlike model.reload. Any explanation and how to fix?

推荐答案

有人知道为什么Tree面对这个问题吗?

Any idea why this problem facing me with the Tree?

如下所示,正确地已同步时,结果是一样的.如此处所示,您可以使用expandRow()scrollPathToVisible()控制可见性.使用Thread.sleep()只会阻塞调用它的线程.由于Swing是单线程,因此结果是不可预测的.而是使用 java.swing.Timer

As shown below, when correctly synchronized, the results are the same. As shown here, you can control visibility using expandRow() and scrollPathToVisible(). Using Thread.sleep() will simply block the thread on which it is called. Because Swing is single-threaded, the results are unpredictable. Instead use java.swing.Timer or SwingWorker as needed.

尝试在添加节点和扩展任何路径之间稍作休息,在继续代码中,问题将按照我的问题中所述出现.

Try to put some sleep between adding nodes and expand any path and in the continue code the problem will appear as stated in my question.

由于提及的原因,使用Thread.sleep()的结果不可靠.使用java.swing.Timer揭示了问题:nodeChanged()反映了节点本身的更改.因为您已更改节点的子级,所以请调用nodeStructureChanged().

For the reasons mentioned, results using Thread.sleep() are not reliable. Using java.swing.Timer reveals the problem: nodeChanged() reflects changes to the node itself. Because you've changed the children of the node, invoke nodeStructureChanged() instead.

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.Timer;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

public class Test {

    private final JFrame frame;
    private final JTree tree;
    private final DefaultMutableTreeNode root;
    private final DefaultTreeModel model;
    private final Map<String, DefaultMutableTreeNode> treeMap;
    private final boolean reload;
    private int index;
    private final String[] folders = {
        "Data", "trial 0",
        "Data/trial 0", "trial 1",
        "Data/trial 0/trial 1", "trial 2",
        "Data", "trial 1",
        "Data/trial 1", "trial 2",
        "Data", "trial 2"
    };

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new Test(true);
            new Test(false);
        });
    }

    public Test(boolean reload) {
        this.reload = reload;
        frame = new JFrame(String.valueOf(reload));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        treeMap = new HashMap<>();
        root = new DefaultMutableTreeNode("Data");
        model = new DefaultTreeModel(root);
        tree = new JTree(model);
        treeMap.put("Data", root);
        frame.add(tree, BorderLayout.WEST);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        Timer t = new Timer(100, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (index < folders.length) {
                    addNewFolder(folders[index++], folders[index++]);
                    for (int i = 0; i < tree.getRowCount(); i++) {
                        tree.expandRow(i);
                    }
                    frame.pack();
                }
            }
        });
        t.start();
    }

    private void addNewFolder(String path, String name) {
        DefaultMutableTreeNode currentNode = treeMap.get(path);
        DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(name);
        currentNode.add(childNode);
        treeMap.put(path + "/" + name, childNode);
        if (reload) {
            model.reload();
        } else {
            model.nodeStructureChanged(currentNode);
        }
    }
}

这篇关于JTree model.nodechanged(Node)丢失数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆