CheckBoxNodeTree示例 - 如何在CheckBoxNodeEditor中正确实现itemlistener?

时间:2013-10-10 09:44:30

标签: java swing jtree jcheckbox

我正在使用此实现来创建我的JTree: https://github.com/imagej/imagej/blob/ee3c360949/ui/swing/util/src/test/java/imagej/util/swing/tree/CheckBoxTreeSample.java

我试图在CheckBoxNodeEditor中搜索创建ItemListener的正确方法,并自己尝试了一些东西,到目前为止还没有工作。我已经为JTree和TreeSelectionListener实现了一个MouseListener,所以我需要这个itemlistener吗?现在我的应用程序在没有itemlistener的情况下工作了,但我担心以后我会需要它。

Kleopatra已在本文中说明了原始代码的一些错误。此外Kleopatra说actionListener可以做到这一点,所以也许我应该检查出来? : Multiple ITEM_STATE_CHANGED events from jcheckbox in jtree

此论坛中的硬连线帖子有助于不向编辑添加多个听众:http://www.java-forums.org/awt-swing/10389-jcheckboxes-jtree-nodes.html

因此,通过hardwire的方法,我可以决定只想在面板中添加一个侦听器,但是由于每次单击JTree时都会创建一个新的侦听器,它仍会触发很多事件?

这是CheckBoxNodeEditor的原始代码(减去一些节省空间的方法和其他涉及的类)。如果您同意,我将从侦听器中删除此方法并使用我创建的两个侦听器(TreeSelection和MouseListener):

class CheckBoxNodeEditor extends AbstractCellEditor implements TreeCellEditor {

  CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
  public static int clickCount = 0;

  ChangeEvent changeEvent = null;

  JTree tree;

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

  public Object getCellEditorValue() {
    ...
  }

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

      System.out.println("getTreeCellEditorComponent method called!");

      System.out.println(String.valueOf(clickCount++));

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

    // editor always selected / focused
    ItemListener itemListener = new ItemListener() {
      public void itemStateChanged(ItemEvent itemEvent) {

我实际删除了接下来的三行:

JCheckBox item = (JCheckBox)itemEvent.getItem();
System.out.println(itemEvent.paramString());
System.out.println("item "+item.getText()+" state Changed!");
          if (stopCellEditing()) {
              fireEditingStopped();
          }
      }
    };
    if (editor instanceof JCheckBox) {
      ((JCheckBox) editor).addItemListener(itemListener);
    }

    return editor;
  }
}

好的,我看到ItemListener控制了复选框。因此,每个复选框实际上都分配了它自己的监听器。如何为所有复选框/节点添加一个?

1 个答案:

答案 0 :(得分:1)

  • 把所有东西放在一起,toString用于覆盖DefaultXxxXxx中针对non_Vector数组类型的几个方法,可以删除

enter image description here

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
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 JCheckBoxJTreeEditor {
private JFrame frame = new JFrame("CheckBox Tree");
    public JCheckBoxJTreeEditor() {        
        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.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(scrollPane);
        frame.setSize(400, 250);
        frame.setVisible(true);
    }

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new JCheckBoxJTreeEditor();
            }
        });
    }
}

class CheckBoxNodeRenderer implements TreeCellRenderer {

    private JCheckBox leafRenderer = new JCheckBox();
    private DefaultTreeCellRenderer nonLeafRenderer = new DefaultTreeCellRenderer();
    private 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");
    }

    @Override
    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 {

    private CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
    private ChangeEvent changeEvent = null;
    private JTree tree;

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

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

    @Override
    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;
    }

    @Override
    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);
        ItemListener itemListener = new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent itemEvent) {
                if (stopCellEditing()) {
                    fireEditingStopped();
                }
            }
        };
        if (editor instanceof JCheckBox) {
            ((JCheckBox) editor).addItemListener(itemListener);
        }
        return editor;
    }
}

class CheckBoxNode {

    private String text;
    private 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;
    }

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

class NamedVector extends Vector {

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

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