【问题标题】:Restricting the addition of nodes of a JTree except for the 1st level child限制除了第一级子节点之外的 JTree 节点的添加
【发布时间】:2015-05-07 21:34:11
【问题描述】:

我一直在尝试很多方法来限制我的代码仅将节点添加到第一级。这意味着用户只能将节点添加到 JTree 的第一级子级。

在我的程序中添加节点可以通过两种方式完成 1.添加节点按钮 2.选择>右键单击>添加节点(在这里,如果选择了非一级子节点,我想禁用此行为。虽然这是一个很长的镜头)

我需要一个允许在其他级别添加节点的验证。谢谢!

这是工作代码:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

public class ProblemTree extends JFrame {

    private DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
    private DefaultTreeModel model = new DefaultTreeModel(root);
    private JTree tree = new JTree(model);
    private JButton addButton = new JButton("Add Node to 1st level only");

    public ProblemTree() {
        DefaultMutableTreeNode n1 = new DefaultMutableTreeNode(
                "1st level: Child 1");
        n1.add(new DefaultMutableTreeNode("2nd level: Child l"));
        DefaultMutableTreeNode n2 = new DefaultMutableTreeNode(
                "1st level: Child 2");
        n2.add(new DefaultMutableTreeNode("2nd level: Child 2"));
        DefaultMutableTreeNode n3 = new DefaultMutableTreeNode(
                "1st level: Child 3");
        n3.add(new DefaultMutableTreeNode("2nd level: Child 3"));

        root.add(n1);
        root.add(n2);
        root.add(n3);

        tree.setEditable(true);
        tree.setSelectionRow(0);
        tree.setRootVisible(true);
        tree.setShowsRootHandles(true);

        final JPopupMenu popupMenu = new JPopupMenu();
        JMenuItem runTask = new JMenuItem("New Node for 1st level only =( ");
        runTask.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) tree
                        .getLastSelectedPathComponent();
                if (selNode == null) {
                    return;
                }
                DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(
                        "New Node");
                model.insertNodeInto(newNode, selNode, selNode.getChildCount());

                TreeNode[] nodes = model.getPathToRoot(newNode);
                TreePath path = new TreePath(nodes);
                tree.scrollPathToVisible(path);
                tree.setSelectionPath(path);
                tree.startEditingAtPath(path);
            }
        });
        popupMenu.add(runTask);
        tree.setComponentPopupMenu(popupMenu);

        JScrollPane scrollPane = new JScrollPane(tree);
        getContentPane().add(scrollPane, BorderLayout.CENTER);

        JPanel panel = new JPanel();

        addButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) tree
                        .getLastSelectedPathComponent();
                if (selNode == null) {
                    return;
                }
                DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(
                        "New Node");
                model.insertNodeInto(newNode, selNode, selNode.getChildCount());

                TreeNode[] nodes = model.getPathToRoot(newNode);
                TreePath path = new TreePath(nodes);
                tree.scrollPathToVisible(path);
                tree.setSelectionPath(path);
                tree.startEditingAtPath(path);
            }
        });
        panel.add(addButton);

        getContentPane().add(panel, BorderLayout.SOUTH);
        setSize(700, 400);
        setVisible(true);
    }

    public static void main(String[] arg) {
        ProblemTree pt = new ProblemTree();
    }
}

【问题讨论】:

  • 您可以同时使用 TreeModel 和自定义 TreeNode,这样当调用 insertNodeInto 之类的东西时,您可以检查父节点是否为第一级节点,如果不是,则拒绝插入.您的自定义节点还可以进一步限制子节点的添加,因此您的第一级节点将只接受非可变树节点......作为一个想法
  • @MadProgrammer 那么应该调用 model.reload
  • @mKorbel 我不这么认为,insertNodeInto 应该触发和事件通知,调用model.reload 就像在AbstractTableModel 上调用fireTableStructureChanged,这将导致树完全重绘,会影响当前展开的节点...
  • @mKorbel 同意重新绘制,但您可能会在 JTree 视图中丢失最后插入的节点,这可能是 JTree(以及相关)API 中缺少抽象的原因之一,它无法正常工作在某些情况下,AFAIK 在这里几次

标签: java swing validation nodes jtree


【解决方案1】:

直接替换

tree.setComponentPopupMenu(popupMenu); 

与:

tree.addMouseListener(new MouseAdapter() {
    @Override
        public void mousePressed(MouseEvent e) {
        if (SwingUtilities.isRightMouseButton(e)) {
            int row = tree.getClosestRowForLocation(e.getX(), e.getY());
            tree.setSelectionRow(row);
            if (tree.getSelectionPath().getPathCount() == 2) {
                popupMenu.show(e.getComponent(), e.getX(), e.getY());
            }
        }
    }
});

并控制您的按钮添加:

addButton.setEnabled(false);
tree.addTreeSelectionListener(new TreeSelectionListener() {
    @Override
    public void valueChanged(TreeSelectionEvent e) {
        addButton.setEnabled((tree.getSelectionPath().getPathCount() == 2));
    }
});

【讨论】:

  • 你是一个了不起的家伙 DoubleMa!
猜你喜欢
  • 2012-09-01
  • 2011-12-17
  • 2011-01-29
  • 1970-01-01
  • 1970-01-01
  • 2012-04-06
  • 1970-01-01
  • 2011-08-03
  • 1970-01-01
相关资源
最近更新 更多