当前位置: 首页 > 知识库问答 >
问题:

带有可选节点的复选框JTree

阳宗清
2023-03-14

我在这里使用这个示例代码创建一个JTree,其中所有的叶子都有一个复选框。我遇到的问题是,我还需要能够选择节点对象,而不必勾选复选框。在我的用例中,勾选复选框将使某些内容可见或隐藏,但选择节点将允许在UI的单独部分编辑对象。最好的方法是什么?是否可以检测何时单击复选框的“框”部分,或者是否选中节点?

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.util.EventObject;
import java.util.Vector;
import javax.swing.AbstractCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;

public class CheckBoxNodeTreeSample {
    public static void main(String args[]) {
            JFrame frame = new JFrame("CheckBox Tree");

            CheckBoxNode accessibilityOptions[] = {
                            new CheckBoxNode(
                                            "Move system caret with focus/selection changes", false),
                            new CheckBoxNode("Always expand alt text for images", true) };
            CheckBoxNode browsingOptions[] = {
                            new CheckBoxNode("Notify when downloads complete", true),
                            new CheckBoxNode("Disable script debugging", true),
                            new CheckBoxNode("Use AutoComplete", true),
                            new CheckBoxNode("Browse in a new process", false) };
            Vector accessVector = new NamedVector("Accessibility",
                            accessibilityOptions);
            Vector browseVector = new NamedVector("Browsing", browsingOptions);
            Object rootNodes[] = { accessVector, browseVector };
            Vector rootVector = new NamedVector("Root", rootNodes);
            JTree tree = new JTree(rootVector);

            CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
            tree.setCellRenderer(renderer);

            tree.setCellEditor(new CheckBoxNodeEditor(tree));
            tree.setEditable(true);

            JScrollPane scrollPane = new JScrollPane(tree);
            frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
            frame.setSize(300, 150);
            frame.setVisible(true);
    }
}

class CheckBoxNodeRenderer implements TreeCellRenderer {
    private JCheckBox leafRenderer = new JCheckBox();

    private DefaultTreeCellRenderer nonLeafRenderer = new DefaultTreeCellRenderer();

    Color selectionBorderColor, selectionForeground, selectionBackground,
                    textForeground, textBackground;

    protected JCheckBox getLeafRenderer() {
            return leafRenderer;
    }

    public CheckBoxNodeRenderer() {
            Font fontValue;
            fontValue = UIManager.getFont("Tree.font");
            if (fontValue != null) {
                    leafRenderer.setFont(fontValue);
            }
            Boolean booleanValue = (Boolean) UIManager
                            .get("Tree.drawsFocusBorderAroundIcon");
            leafRenderer.setFocusPainted((booleanValue != null)
                            && (booleanValue.booleanValue()));

            selectionBorderColor = UIManager.getColor("Tree.selectionBorderColor");
            selectionForeground = UIManager.getColor("Tree.selectionForeground");
            selectionBackground = UIManager.getColor("Tree.selectionBackground");
            textForeground = UIManager.getColor("Tree.textForeground");
            textBackground = UIManager.getColor("Tree.textBackground");
    }

    public Component getTreeCellRendererComponent(JTree tree, Object value,
                    boolean selected, boolean expanded, boolean leaf, int row,
                    boolean hasFocus) {

            Component returnValue;
            if (leaf) {

                    String stringValue = tree.convertValueToText(value, selected,
                                    expanded, leaf, row, false);
                    leafRenderer.setText(stringValue);
                    leafRenderer.setSelected(false);

                    leafRenderer.setEnabled(tree.isEnabled());

                    if (selected) {
                            leafRenderer.setForeground(selectionForeground);
                            leafRenderer.setBackground(selectionBackground);
                    } else {
                            leafRenderer.setForeground(textForeground);
                            leafRenderer.setBackground(textBackground);
                    }

                    if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
                            Object userObject = ((DefaultMutableTreeNode) value)
                                            .getUserObject();
                            if (userObject instanceof CheckBoxNode) {
                                    CheckBoxNode node = (CheckBoxNode) userObject;
                                    leafRenderer.setText(node.getText());
                                    leafRenderer.setSelected(node.isSelected());
                            }
                    }
                    returnValue = leafRenderer;
            } else {
                    returnValue = nonLeafRenderer.getTreeCellRendererComponent(tree,
                                    value, selected, expanded, leaf, row, hasFocus);
            }
            return returnValue;
    }
}

class CheckBoxNodeEditor extends AbstractCellEditor implements TreeCellEditor {

    CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();

    ChangeEvent changeEvent = null;

    JTree tree;

    public CheckBoxNodeEditor(JTree tree) {
            this.tree = tree;
    }

    public Object getCellEditorValue() {
            JCheckBox checkbox = renderer.getLeafRenderer();
            CheckBoxNode checkBoxNode = new CheckBoxNode(checkbox.getText(),
                            checkbox.isSelected());
            return checkBoxNode;
    }

    public boolean isCellEditable(EventObject event) {
            boolean returnValue = false;
            if (event instanceof MouseEvent) {
                    MouseEvent mouseEvent = (MouseEvent) event;
                    TreePath path = tree.getPathForLocation(mouseEvent.getX(),
                                    mouseEvent.getY());
                    if (path != null) {
                            Object node = path.getLastPathComponent();
                            if ((node != null) && (node instanceof DefaultMutableTreeNode)) {
                                    DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node;
                                    Object userObject = treeNode.getUserObject();
                                    returnValue = ((treeNode.isLeaf()) && (userObject instanceof CheckBoxNode));
                            }
                    }
            }
            return returnValue;
    }

    public Component getTreeCellEditorComponent(JTree tree, Object value,
                    boolean selected, boolean expanded, boolean leaf, int row) {

            Component editor = renderer.getTreeCellRendererComponent(tree, value,
                            true, expanded, leaf, row, true);

            // editor always selected / focused
            ItemListener itemListener = new ItemListener() {
                    public void itemStateChanged(ItemEvent itemEvent) {
                            if (stopCellEditing()) {
                                    fireEditingStopped();
                            }
                    }
            };
            if (editor instanceof JCheckBox) {
                    ((JCheckBox) editor).addItemListener(itemListener);
            }

            return editor;
    }
}

class CheckBoxNode {
    String text;

    boolean selected;

    public CheckBoxNode(String text, boolean selected) {
            this.text = text;
            this.selected = selected;
    }

    public boolean isSelected() {
            return selected;
    }

    public void setSelected(boolean newValue) {
            selected = newValue;
    }

    public String getText() {
            return text;
    }

    public void setText(String newValue) {
            text = newValue;
    }

    public String toString() {
            return getClass().getName() + "[" + text + "/" + selected + "]";
    }
}

class NamedVector extends Vector {
    String name;

    public NamedVector(String name) {
            this.name = name;
    }

    public NamedVector(String name, Object elements[]) {
            this.name = name;
            for (int i = 0, n = elements.length; i < n; i++) {
                    add(elements[i]);
            }
    }

    public String toString() {
            return "[" + name + "]";
    }
}

我看到的另一个错误是,当文件夹有子元素时,文件夹左侧的指示器正确显示文件夹已打开:

但是如果'文件夹'是空的,该指示器最初会出现,但是当你打开它时,它会消失。如果文件夹是空的,我认为这不应该出现。

共有1个答案

穆华彩
2023-03-14

我能够得到这个工作与@Mad程序员建议解耦复选框和文本,以及删除树引用在CheckBoxNodeEditor,更新的代码如下:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.util.EventObject;
import java.util.Vector;

import javax.swing.AbstractCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;

public class CheckBoxNodeTreeSample 
{
    
    private JTree tree;

    public static void main(String... s)
    {
        new CheckBoxNodeTreeSample();
    }

    public CheckBoxNodeTreeSample() 
    {
        JFrame frame = new JFrame("CheckBox Tree");
    
        CheckBoxNode accessibilityOptions[] = {
                    new CheckBoxNode(
                                    "Move system caret with focus/selection changes", false),
                    new CheckBoxNode("Always expand alt text for images", true) };
        CheckBoxNode browsingOptions[] = {
                    new CheckBoxNode("Notify when downloads complete", true),
                    new CheckBoxNode("Disable script debugging", true),
                    new CheckBoxNode("Use AutoComplete", true),
                    new CheckBoxNode("Browse in a new process", false) };
        Vector accessVector = new NamedVector("Accessibility",
                    accessibilityOptions);
        Vector browseVector = new NamedVector("Browsing", browsingOptions);
        Object rootNodes[] = { accessVector, browseVector };
        Vector rootVector = new NamedVector("Root", rootNodes);
        tree = new JTree(rootVector);
   
    
        CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
        tree.setCellRenderer(renderer);
        tree.setCellEditor(new CheckBoxNodeEditor());
        tree.setEditable(true);

        JScrollPane scrollPane = new JScrollPane(tree);
        frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
        frame.setSize(360, 260);
        frame.setVisible(true);
    }
}

class CheckBoxPanel extends JPanel
{
    public JCheckBox checkBox;
    public JLabel label;

    public CheckBoxPanel() 
    { 
        super();
    
        checkBox = new JCheckBox();
        label = new JLabel();
    
        checkBox.setBorder(new EmptyBorder(0, 0, 0, 0));

        add(checkBox);
        add(label);
    }
}

class CheckBoxNodeRenderer implements TreeCellRenderer 
{
    private CheckBoxPanel leafRenderer = new CheckBoxPanel();

    private DefaultTreeCellRenderer nonLeafRenderer = new DefaultTreeCellRenderer();

    Color selectionBorderColor, selectionForeground, selectionBackground,
                    textForeground, textBackground;

    protected CheckBoxPanel getLeafRenderer() 
    {
            return leafRenderer;
    }

    public CheckBoxNodeRenderer() {
            Font fontValue;
            fontValue = UIManager.getFont("Tree.font");
            if (fontValue != null) {
                    leafRenderer.checkBox.setFont(fontValue);
                    leafRenderer.label.setFont(fontValue);
            }
            Boolean booleanValue = (Boolean) UIManager
                            .get("Tree.drawsFocusBorderAroundIcon");
            leafRenderer.checkBox.setFocusPainted((booleanValue != null)
                            && (booleanValue.booleanValue()));

            selectionBorderColor = UIManager.getColor("Tree.selectionBorderColor");
            selectionForeground = UIManager.getColor("Tree.selectionForeground");
            selectionBackground = UIManager.getColor("Tree.selectionBackground");
            textForeground = UIManager.getColor("Tree.textForeground");
            textBackground = UIManager.getColor("Tree.textBackground");
    }

    public Component getTreeCellRendererComponent(JTree tree, Object value,
                    boolean selected, boolean expanded, boolean leaf, int row,
                    boolean hasFocus) {

            Component returnValue;
            if (leaf) {

                    String stringValue = tree.convertValueToText(value, selected,
                                    expanded, leaf, row, false);
                    
                    leafRenderer.checkBox.setSelected(false);
                    leafRenderer.label.setText(stringValue);

                    leafRenderer.setEnabled(tree.isEnabled());

                    if (selected) {
                            leafRenderer.setForeground(selectionForeground);
                            leafRenderer.setBackground(selectionBackground);
                    } else {
                            leafRenderer.setForeground(textForeground);
                            leafRenderer.setBackground(textBackground);
                    }

                    if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
                            Object userObject = ((DefaultMutableTreeNode) value)
                                            .getUserObject();
                            if (userObject instanceof CheckBoxNode) {
                                    CheckBoxNode node = (CheckBoxNode) userObject;                                        
                                    leafRenderer.checkBox.setSelected(node.isSelected());
                                    leafRenderer.label.setText(node.getText());
                            }
                    }
                    returnValue = leafRenderer;
            } else {
                    returnValue = nonLeafRenderer.getTreeCellRendererComponent(tree,
                                    value, selected, expanded, leaf, row, hasFocus);
            }
            return returnValue;
    }
}

class CheckBoxNodeEditor extends AbstractCellEditor implements TreeCellEditor {

    CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();

    ChangeEvent changeEvent = null;

    public Object getCellEditorValue() {
            CheckBoxPanel checkBoxPanel = renderer.getLeafRenderer();
            CheckBoxNode checkBoxNode = new CheckBoxNode(checkBoxPanel.label.getText(),
                    checkBoxPanel.checkBox.isSelected());
            return checkBoxNode;
    }

    public boolean isCellEditable(EventObject event) {
            boolean returnValue = false;
            if (event instanceof MouseEvent) {
                    MouseEvent mouseEvent = (MouseEvent) event;
                    JTree tree = (JTree)event.getSource();

                    TreePath path = tree.getPathForLocation(mouseEvent.getX(),
                                    mouseEvent.getY());
                    if (path != null) {
                            Object node = path.getLastPathComponent();
                            if ((node != null) && (node instanceof DefaultMutableTreeNode)) {
                                    DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node;
                                    Object userObject = treeNode.getUserObject();
                                    returnValue = ((treeNode.isLeaf()) && (userObject instanceof CheckBoxNode));
                            }
                    }
            }
            return returnValue;
    }

    public Component getTreeCellEditorComponent(JTree tree, Object value,
                    boolean selected, boolean expanded, boolean leaf, int row)  {

            Component editor = renderer.getTreeCellRendererComponent(tree, value,
                            true, expanded, leaf, row, true);

            // editor always selected / focused
            ItemListener itemListener = new ItemListener() {
                    public void itemStateChanged(ItemEvent itemEvent) {
                            if (stopCellEditing()) {
                                    fireEditingStopped();
                            }
                    }
            };
            
            if (editor instanceof CheckBoxPanel) 
            {
                ((CheckBoxPanel) editor).checkBox.addItemListener(itemListener);
            }

            return editor;
    }
}

class CheckBoxNode {
    String text;

    boolean selected;

    public CheckBoxNode(String text, boolean selected) {
            this.text = text;
            this.selected = selected;
    }

    public boolean isSelected() {
            return selected;
    }

    public void setSelected(boolean newValue) {
            selected = newValue;
    }

    public String getText() {
            return text;
    }

    public void setText(String newValue) {
            text = newValue;
    }

    public String toString() {
            return getClass().getName() + "[" + text + "/" + selected + "]";
    }
}

class NamedVector extends Vector 
{
    String name;

    public NamedVector(String name) {
            this.name = name;
    }

    public NamedVector(String name, Object elements[]) {
            this.name = name;
            for (int i = 0, n = elements.length; i < n; i++) {
                    add(elements[i]);
            }
    }

    public String toString() {
            return "[" + name + "]";
    }
}
 类似资料:
  • 问题内容: 我需要将复选框添加到JTree。自定义TreeCellRenderer / TreeCellEditor似乎是正确的方法。到目前为止,我在此网页中使用了CheckBoxNodeRenderer方法。除了两件事,它可以正常工作: 复选框上方+下方有额外的空格;我想使其与常规JTree相同。 我想区分单击复选框本身(应尝试切换复选框)和单击与复选框相关联的文本(应允许事件侦听器将此解释为单

  • 问题内容: 是否可以将复选框代替“链接名称”? 如果是这样怎么办? 谢谢, 问题答案: 是的,当然有可能。您可以使用标准复选框: 然后在单独的javascript文件中使用jQuery订阅此复选框的change事件,并毫不客气地对其进行AJAXify:

  • 我一直在研究这个问题,但我找不到一个带有复选框的get drawable的解决方案。我试图做的是,当你点击这个特定的复选框时,它会过滤相应颜色的复选框。顺便说一下,这是一个片段。所以,我有可以是红色、黄色或绿色的复选框。如果用户点击它们,它会改变颜色。例如,我有一个黄色的复选框,它是chkProgress,当它被单击时,我想找到所有黄色的复选框,并筛选黄色的复选框。所以,我有可绘制的ID,我需要得

  • 问题内容: 如何创建带有可单击标签的HTML复选框(这意味着单击标签可以打开/关闭该复选框)? 问题答案: 方法1:包装标签标签 将复选框包装在标签内: 方法2:使用属性 使用属性(匹配复选框): 注意 :ID在页面上必须是唯一的! 说明 由于其他答案均未提及,因此标签最多可以包含1个输入并忽略该属性,并且将假定该属性用于其中的输入。 w3.org的摘录(重点介绍): [for属性]显式地将要定义

  • 问题内容: 我正在尝试选中一个复选框的所有复选框。但是该怎么做呢? 这是我的HTML: 我创建了一个额外的复选框以选择并取消选择所有复选框。 JS: 我也尝试过,但是没有一个对我有用:( 问题答案: 您错过了容器的div 和和。 是正确的变体。 https://jsfiddle.net/0vb4gapj/1/

  • 问题内容: 我有两行复选框。当用户单击任何单个复选框(在特定行中)时,我想在PHP的总和中添加一个数字。如果他取消选择单个复选框,那么我想实时地从总数中减去而不刷新页面。 我的问题是我的AJAX调用的数据字段中有什么内容? 这是正确的方法吗? HTML JQUERY PHP 问题答案: 尝试: