【问题标题】:JTree model.nodechanged(Node) loses dataJTree model.nodechanged(Node) 丢失数据
【发布时间】:2016-06-23 03:31:33
【问题描述】:

我正在使用JTree 测试一些代码,我注意到model.reload() 提供的输出与model.nodeChanged(currentNode) 不同。正确的输出来自model.reload()。这是相同代码的两个输出:

我的代码如下:

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 不同。任何解释以及如何解决?

【问题讨论】:

  • 使用逻辑一致的缩进代码行和块的形式。缩进是为了让代码流更容易理解! IDE 通常有一个shortcut for formatting code..
  • 我做了自动格式化,但没有帮助
  • 好吧,祝你好运。生命太短暂,无法处理未格式化的代码。
  • !我不明白你的意思!
  • 您未格式化的代码很难阅读,但显然是错误的:不要Initial Thread上休眠; Concurrency in SwingHow to Use Swing Timers

标签: java eclipse swing jtree


【解决方案1】:

知道为什么Tree 会遇到这个问题吗?

如下图,当正确synchronized时,结果是一样的。如图here 所示,您可以使用expandRow()scrollPathToVisible() 控制可见性。使用Thread.sleep() 只会阻塞调用它的线程。因为 Swing 是single-threaded,所以结果是不可预测的。而是根据需要使用java.swing.TimerSwingWorker

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

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

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);
        }
    }
}

【讨论】:

  • 在没有机会扩展任何路径的情况下完成所有操作后,我得到了相同的结果。更具体地说,我只有在线程处于睡眠状态时扩展任何路径时才得到这种差异。
  • 尝试在添加节点和扩展任何路径之间稍作休息,在继续代码中,问题将如我的问题中所述出现
  • 我已经在上面详细说明了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-31
  • 2016-07-05
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多