同时展开和折叠具有相同结构的两棵树

TSG

我要修改此链接中给定的Swing示例中的标准JTree->动态树示例该应用的屏幕截图如下:DynamicTreeDemo

在此处输入图片说明

我想使用这种结构来维护两棵树,它们都具有完全相同的结构。当通过鼠标单击折叠/展开任何一个时,我都应该能够同时折叠和展开!
同样,当用户从任一棵树中选择一个节点时,另一棵树中的相应节点也应突出显示。
一棵树可能包含文件/文件夹作为节点,而另一棵树可能具有创建时间作为节点。

我可以在每个DynamicTree对象中仅使用一个Jtree对象来使其工作吗?(请参阅示例以查看这些对象是什么。)是否有任何方法可以使Jtree仅存储一个对象,而该对象包含来自每棵树的相应节点的数据,而是将这些数据显示在单独的树上?

当前,我正在使用两个Jtree,并且可以通过将两个父级和两个子级作为add函数的输入并将相应的子级添加到相应的父级来添加节点。
但是,在删除/扩展/折叠功能中,我需要从两棵树中删除/扩展/折叠两个对应的节点。我该怎么做呢?

我是java swing的新手,但不是Java编程的人。因此,请阐明需要了解Jswing的部分。

提前致谢。

疯狂程序员

因此,诀窍是使用单个TreeModel,链接树的树SelectionModel和两个自定义TreeCellRenderer并使用TreeExpansionListener能够确定哪棵树展开/折叠并镜像结果的功能。

基本上,每个树共享相同的TreeModelSelectionModel,这让我们的生活更简单,因为他们都将要被这两个模型方面的变化。

扩展/折叠要困难一些,因为这需要通过一个custom处理,该customTreeExpansionListener可以检测到谁触发了事件,然后将更改通知给相反的树。

接下来,我使用一个通用的“数据对象”,其中包含有关应该由树的树显示的数据的基本信息。

最后,我使用两个不同TreeCellRenderer的来呈现由维护的数据的不同方面TreeModel

树

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;

public class DynamicTreeDemo extends JPanel implements ActionListener {

    protected static final SimpleDateFormat SDF = new SimpleDateFormat("HH:mm:ss");

    private int newNodeSuffix = 1;
    private static String ADD_COMMAND = "add";
    private static String REMOVE_COMMAND = "remove";
    private static String CLEAR_COMMAND = "clear";

    private DefaultMutableTreeNode rootNode;
    private final DefaultTreeModel treeModel;

    private JTree left;
    private JTree right;

    public DynamicTreeDemo() {
        super(new BorderLayout());

        rootNode = new DefaultMutableTreeNode("Root Node");
        treeModel = new DefaultTreeModel(rootNode);

        left = new JTree(treeModel);
        left.setCellRenderer(new LeftTreeCellRenderer());
        right = new JTree(treeModel);
        right.setCellRenderer(new RightTreeCellRenderer());

        MyExpansionListener expansionListener = new MyExpansionListener(left, right);

        left.addTreeExpansionListener(expansionListener);
        right.addTreeExpansionListener(expansionListener);

        right.setSelectionModel(left.getSelectionModel());

        populateModel();

        JButton addButton = new JButton("Add");
        addButton.setActionCommand(ADD_COMMAND);
        addButton.addActionListener(this);

        JButton removeButton = new JButton("Remove");
        removeButton.setActionCommand(REMOVE_COMMAND);
        removeButton.addActionListener(this);

        JButton clearButton = new JButton("Clear");
        clearButton.setActionCommand(CLEAR_COMMAND);
        clearButton.addActionListener(this);

        JPanel panel = new JPanel(new GridLayout(1, 2));
        panel.add(new JScrollPane(left));
        panel.add(new JScrollPane(right));
        add(panel, BorderLayout.CENTER);

        JPanel buttons = new JPanel(new GridLayout(0, 3));
        buttons.add(addButton);
        buttons.add(removeButton);
        buttons.add(clearButton);
        add(buttons, BorderLayout.SOUTH);
    }

    protected TreeData createNodeData() {
        return new TreeData("New Node " + newNodeSuffix++, SDF.format(new Date()));
    }

    public void populateModel() {
        String p1Name = "Parent 1";
        String p2Name = "Parent 2";

        DefaultMutableTreeNode p1, p2;

        p1 = addObject(null, p1Name);
        p2 = addObject(null, p2Name);

        addObject(p1, createNodeData());
        addObject(p1, createNodeData());

        addObject(p2, createNodeData());
        addObject(p2, createNodeData());

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();

        if (ADD_COMMAND.equals(command)) {
            // Add button clicked
            addObject(createNodeData());
        } else if (REMOVE_COMMAND.equals(command)) {
            // Remove button clicked
            removeCurrentNode();
        } else if (CLEAR_COMMAND.equals(command)) {
            // Clear button clicked.
            clear();
        }
    }

    /**
     * Create the GUI and show it. For thread safety, this method should be
     * invoked from the event-dispatching thread.
     */
    private static void createAndShowGUI() {
        // Create and set up the window.
        JFrame frame = new JFrame("DynamicTreeDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Create and set up the content pane.
        DynamicTreeDemo newContentPane = new DynamicTreeDemo();
        newContentPane.setOpaque(true); // content panes must be opaque
        frame.setContentPane(newContentPane);

        // Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        // Schedule a job for the event-dispatching thread:
        // creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    /**
     * Remove all nodes except the root node.
     */
    public void clear() {
        rootNode.removeAllChildren();
        treeModel.reload();
    }

    /**
     * Add child to the currently selected node.
     */
    public DefaultMutableTreeNode addObject(Object child) {
        DefaultMutableTreeNode parentNode = null;
        TreePath parentPath = left.getSelectionPath();

        if (parentPath == null) {
            parentNode = rootNode;
        } else {
            parentNode = (DefaultMutableTreeNode) (parentPath.getLastPathComponent());
        }

        return addObject(parentNode, child, true);
    }

    public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
            Object child) {
        return addObject(parent, child, false);
    }

    public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
            Object child, boolean shouldBeVisible) {
        DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(child);

        if (parent == null) {
            parent = rootNode;
        }

        // It is key to invoke this on the TreeModel, and NOT DefaultMutableTreeNode
        treeModel.insertNodeInto(childNode, parent, parent.getChildCount());

        // Make sure the user can see the lovely new node.
        if (shouldBeVisible) {
            left.scrollPathToVisible(new TreePath(childNode.getPath()));
            right.scrollPathToVisible(new TreePath(childNode.getPath()));
        }
        return childNode;
    }

    /**
     * Remove the currently selected node.
     */
    public void removeCurrentNode() {
        TreePath currentSelection = left.getSelectionPath();
        if (currentSelection != null) {
            DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) (currentSelection
                    .getLastPathComponent());
            MutableTreeNode parent = (MutableTreeNode) (currentNode.getParent());
            if (parent != null) {
                treeModel.removeNodeFromParent(currentNode);
                return;
            }
        }

    }

    public class TreeData {

        private String left;
        private String right;

        public TreeData(String left, String right) {
            this.left = left;
            this.right = right;
        }

        public String getLeft() {
            return left;
        }

        public String getRight() {
            return right;
        }

    }

    public class LeftTreeCellRenderer extends DefaultTreeCellRenderer {

        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            if (value instanceof DefaultMutableTreeNode) {
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
                Object userData = node.getUserObject();
                if (userData instanceof TreeData) {
                    value = ((TreeData) userData).getLeft();
                }
            }
            return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
        }

    }

    public class RightTreeCellRenderer extends DefaultTreeCellRenderer {

        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            if (value instanceof DefaultMutableTreeNode) {
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
                Object userData = node.getUserObject();
                if (userData instanceof TreeData) {
                    value = ((TreeData) userData).getRight();
                }
            }
            return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
        }

    }

    public class MyExpansionListener implements TreeExpansionListener {

        private JTree left;
        private JTree right;

        public MyExpansionListener(JTree left, JTree right) {
            this.left = left;
            this.right = right;
        }

        @Override
        public void treeExpanded(TreeExpansionEvent event) {
            TreePath path = event.getPath();
            if (event.getSource() == left) {
                right.expandPath(path);
            } else {
                left.expandPath(path);
            }
        }

        @Override
        public void treeCollapsed(TreeExpansionEvent event) {
            TreePath path = event.getPath();
            if (event.getSource() == left) {
                right.collapsePath(path);
            } else {
                left.collapsePath(path);
            }
        }

    }
}

有关更多详细信息,请参见如何使用树

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何使用级别顺序遍历查找两棵树在结构上是否相同?

来自分类Dev

检查两棵树是否相同

来自分类Dev

在 Haskell 中测试两棵树是否相等和二叉搜索树

来自分类Dev

使用treemodel.js合并两棵树

来自分类Dev

使用jqTree在两棵树之间拖放

来自分类Dev

在jstree中的两棵树之间拖放

来自分类Dev

伪代码比较两棵树

来自分类Dev

比较Python中的两棵树/图

来自分类Dev

在jstree中的两棵树之间拖放

来自分类Dev

比较Python中的两棵树/图

来自分类Dev

是否可以使用嵌套集表示同步两棵树?

来自分类Dev

PHP多维数组将数组内的两棵树合并在一起怎么办?

来自分类Dev

如何使用angularjs和特定的数据结构创建简单的树可展开/可折叠视图

来自分类Dev

使用JavaScript折叠和展开树结构

来自分类Dev

html折叠/展开树

来自分类Dev

展开折叠树

来自分类Dev

html折叠/展开树

来自分类Dev

带有超链接和1单击展开/折叠的Google组织结构图

来自分类Dev

具有两个标签的展开/折叠自调整大小的表格视图单元格

来自分类Dev

具有相同名称和不同模板参数的两个结构如何工作

来自分类Dev

在Python中从具有不同结构和索引的两个数组中获取相同的值

来自分类Dev

Extjs - 树面板根据条件折叠和展开

来自分类Dev

查询以比较具有相同结构的两个表?

来自分类Dev

具有相同结构的两个URL

来自分类Dev

展开具有相同元素的列表

来自分类Dev

展开和折叠JavaScript

来自分类Dev

展开和折叠CardView

来自分类Dev

具有一棵树的随机森林的性能要比单个决策树差?

来自分类Dev

函数和结构在C ++中具有相同的名称