本文介绍了JTree选择问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个由JLabel和JComboBox组成的节点的JTree。我想要的是,当点击时,所选的JComboBox将展开,但似乎第一次点击是由JTree本身(?)消耗的,所以我必须点击它两次。

I've got a JTree with nodes made up of a JLabel and a JComboBox. What I want is that when clicked on, the selected JComboBox will expand, but it seems like the first click is being consumed by the JTree itself (?), so I have to click it twice.

以下是我的代码:

import java.awt.*;
import java.awt.event.*;
import java.util.*;

import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.plaf.ColorUIResource;
import javax.swing.tree.*;

public class JComboBoxJTree extends JPanel {

    final JTree entitiesTree;

    public JComboBoxJTree() {

        entitiesTree = createTree();
        JScrollPane entitiesTreeScrollPane = new JScrollPane(entitiesTree);

        this.setLayout(new GridBagLayout());

        GridBagConstraints c = new GridBagConstraints();

        c.gridx = 0;
        c.gridy = 1;
        c.weightx = 1.0;
        c.weighty = 1.0;
        c.fill = GridBagConstraints.BOTH;
        c.insets = new Insets(0, 5, 0, 5);

        this.add(entitiesTreeScrollPane, c);

        entitiesTree.setBackground(Color.black);
        entitiesTreeScrollPane.setBackground(Color.black);
        this.setBackground(Color.black);

    }

    public static void main(String[] args) {
        try {
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {

                    UIManager.setLookAndFeel(info.getClassName());

                    UIManager.getLookAndFeelDefaults().put("Button.background",
                            Color.BLACK);

                    UIManager.getLookAndFeelDefaults().put(
                            "TextField.background", Color.BLACK);

                    UIManager.getLookAndFeelDefaults().put(
                            "ComboBox.background", Color.BLACK);

                    UIManager.getLookAndFeelDefaults().put(
                            "TextField.foreground", Color.WHITE);

                    UIManager.getLookAndFeelDefaults().put("List.foreground",
                            Color.WHITE);
                    UIManager.getLookAndFeelDefaults().put("List.background",
                            Color.BLACK);

                    UIManager.put("textForeground", Color.white);

                    UIManager.put("info", new ColorUIResource(Color.BLACK));

                    UIManager.put("ScrollPane.background", Color.black);

                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        JComboBoxJTree dialog = new JComboBoxJTree();

        JDialog jd = new JDialog();
        jd.add(dialog);
        jd.pack();
        jd.setVisible(true);
    }

    private static JTree createTree() {
        DefaultMutableTreeNode root = new DefaultMutableTreeNode(new Node(
                "Plugins"));
        root.add(new DefaultMutableTreeNode(new Node("Plugin 1", "Running",
                "Paused", "Stopped")));
        root.add(new DefaultMutableTreeNode(new Node("Plugin 2", "Running",
                "Paused", "Stopped")));
        DefaultMutableTreeNode leaf = new DefaultMutableTreeNode(new Node(
                "Plugin 3", "Running", "Paused", "Stopped"));

        root.add(leaf);

        leaf.add(new DefaultMutableTreeNode(new Node("Plugin 3A", "Running",
                "Paused", "Stopped")));
        leaf.add(new DefaultMutableTreeNode(new Node("Plugin 3B", "Running",
                "Paused", "Stopped")));

        JTree tree = new JTree(root);

        RendererDispatcher rendererDispatcher = new RendererDispatcher(tree);
        RendererDispatcher editorDispatcher = new RendererDispatcher(tree);
        tree.setCellRenderer(rendererDispatcher);
        tree.setCellEditor(editorDispatcher);

        tree.setEditable(true);
        return tree;
    }
}

class Node {

    final String name;
    final String[] plugins;
    boolean selected;
    int selectedPluginIndex;

    public Node(String name, String... plugins) {
        this.name = name;
        this.selected = false;
        this.plugins = plugins;
        if (plugins == null) {
            this.selectedPluginIndex = -1;
        } else {
            this.selectedPluginIndex = 0;
        }
    }

    public boolean isSelected() {
        return selected;
    }

    public void setSelected(boolean selected) {
        this.selected = selected;
    }

    public String toString() {
        return name;
    }

    public int getSelectedPluginIndex() {
        return selectedPluginIndex;
    }

    public void setSelectedPluginIndex(int selectedPluginIndex) {
        this.selectedPluginIndex = selectedPluginIndex;
    }

    public String[] getPlugins() {
        return plugins;
    }
}

class RendererDispatcher extends AbstractCellEditor implements
        TreeCellRenderer, TreeCellEditor {

    final static Color selectionForeground = UIManager
            .getColor("Tree.selectionForeground");
    final static Color selectionBackground = UIManager
            .getColor("Tree.selectionBackground");
    final static Color textForeground = UIManager
            .getColor("Tree.textForeground");
    final static Color textBackground = UIManager
            .getColor("Tree.textBackground");
    final JTree tree;
    final DefaultComboBoxModel comboBoxModel = new DefaultComboBoxModel();
    final JPanel panel = new JPanel();
    JLabel pluginName = new JLabel();
    final JComboBox comboBox = new JComboBox(comboBoxModel);
    final JComponent components[] = { panel, pluginName, comboBox };

    public RendererDispatcher(JTree tree) {
        this.tree = tree;
        Font font = UIManager.getFont("Tree.font");

        panel.add(pluginName);
        setForeground(Color.white);
        setBackground(Color.BLACK);

        if (font != null) {
            this.setFont(font);
        }
    }

    public Component getTreeCellRendererComponent(JTree tree, Object value,
            boolean selected, boolean expanded, boolean leaf, int row,
            boolean hasFocus) {
        final Node node = extractNode(value);

        this.setContents(node);

        this.setEnabled(tree.isEnabled());

        this.setForeground(Color.white);
        this.setBackground(Color.BLACK);

        return this.getComponent();
    }

    public Component getTreeCellEditorComponent(JTree tree, Object value,
            boolean selected, boolean expanded, boolean leaf, int row) {
        return getTreeCellRendererComponent(tree, value, true, expanded, leaf,
                row, true);
    }

    public Object getCellEditorValue() {
        return this.getContents();
    }

    public boolean isCellEditable(final EventObject event) {
        if (!(event instanceof MouseEvent)) {
            return false;
        }

        final MouseEvent mouseEvent = (MouseEvent) event;
        final TreePath path = tree.getPathForLocation(mouseEvent.getX(),
                mouseEvent.getY());
        if (path == null) {
            return false;
        }

        Object node = path.getLastPathComponent();
        if (node == null || (!(node instanceof DefaultMutableTreeNode))) {
            return false;
        }

        DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node;
        Object userObject = treeNode.getUserObject();

        return (userObject instanceof Node);
    }

    private static Node extractNode(Object value) {
        if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
            Object userObject = node.getUserObject();
            if ((userObject != null) && (userObject instanceof Node)) {
                return (Node) userObject;
            }
        }

        return null;
    }

    public void setForeground(final Color foreground) {
        for (int i = 0; i < components.length; i++) {
            components[i].setForeground(foreground);
        }
    }

    public void setBackground(final Color background) {
        for (int i = 0; i < components.length; i++) {
            components[i].setBackground(background);
        }
    }

    public void setFont(final Font font) {
        for (int i = 0; i < components.length; i++) {
            components[i].setFont(font);
        }
    }

    public void setEnabled(final boolean enabled) {
        for (int i = 0; i < components.length; i++) {
            components[i].setEnabled(enabled);
        }
    }

    public void setContents(Node node) {
        // checkBox.setText(node.toString());
        pluginName.setText(node.toString());

        comboBoxModel.removeAllElements();
        if (node.getPlugins().length > 0) {
            panel.add(comboBox);
            for (int i = 0; i < node.getPlugins().length; i++) {
                comboBoxModel.addElement(node.getPlugins()[i]);
            }
        } else {
            panel.remove(comboBox);
        }
    }

    public Object getContents() {
        String title = pluginName.getText();
        String[] plugins = new String[comboBoxModel.getSize()];
        for (int i = 0; i < comboBoxModel.getSize(); i++) {
            plugins[i] = comboBoxModel.getElementAt(i).toString();
        }
        Node node = new Node(title, plugins);
        node.setSelectedPluginIndex(comboBoxModel.getIndexOf(comboBoxModel
                .getSelectedItem()));
        return node;
    }

    public Component getComponent() {
        return panel;
    }
}


推荐答案


  • 这是一个缩短的例子:

  • 这对我使用 Java 1.8.0

    • Here is a shortened example:
    • This works for me on using Java 1.8.0: Bug ID: JDK-8023474 First mousepress doesn't start editing in JTree
    • import java.awt.*;
      import java.awt.event.*;
      import java.util.*;
      import javax.swing.*;
      import javax.swing.tree.*;
      
      public class JComboBoxJTree2 {
        public JComponent makeUI() {
          String[] m = {"Running", "Paused", "Stopped"};
          DefaultMutableTreeNode root = new DefaultMutableTreeNode(new Node("Plugins"));
          root.add(new DefaultMutableTreeNode(new Node("Plugin 1", m)));
          root.add(new DefaultMutableTreeNode(new Node("Plugin 2", m)));
          DefaultMutableTreeNode leaf = new DefaultMutableTreeNode(new Node("Plugin 3", m));
          root.add(leaf);
          leaf.add(new DefaultMutableTreeNode(new Node("Plugin 3A", m)));
          leaf.add(new DefaultMutableTreeNode(new Node("Plugin 3B", m)));
      
          JTree tree = new JTree(root);
          RendererDispatcher rendererDispatcher = new RendererDispatcher(new JComboBox<String>());
          RendererDispatcher editorDispatcher = new RendererDispatcher(new JComboBox<String>());
          tree.setCellRenderer(rendererDispatcher);
          tree.setCellEditor(editorDispatcher);
          tree.setEditable(true);
      
          return new JScrollPane(tree);
        }
        public static void main(String[] args) {
          EventQueue.invokeLater(new Runnable() {
            @Override public void run() {
              createAndShowGUI();
            }
          });
        }
        public static void createAndShowGUI() {
          JFrame f = new JFrame();
          f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
          f.getContentPane().add(new JComboBoxJTree2().makeUI());
          f.setSize(320, 240);
          f.setLocationRelativeTo(null);
          f.setVisible(true);
        }
      }
      
      class Node {
        private final String name;
        private final String[] plugins;
        private int selectedPluginIndex;
        public Node(String name, String... plugins) {
          this.name = name;
          this.plugins = plugins;
        }
        public String toString() {
          return name;
        }
        public int getSelectedPluginIndex() {
          return selectedPluginIndex;
        }
        public void setSelectedPluginIndex(int selectedPluginIndex) {
          this.selectedPluginIndex = selectedPluginIndex;
        }
        public String[] getPlugins() {
          return plugins;
        }
      }
      
      class RendererDispatcher extends DefaultCellEditor implements TreeCellRenderer {
        private final JPanel panel = new JPanel();
        private final JLabel pluginName = new JLabel();
        private final JComboBox<String> comboBox;
        private Node node;
      
        public RendererDispatcher(JComboBox<String> comboBox) {
          super(comboBox);
          this.comboBox = comboBox;
          panel.setOpaque(false);
          panel.add(pluginName);
          panel.add(comboBox);
        }
        @Override public Component getTreeCellRendererComponent(
            JTree tree, Object value, boolean selected, boolean expanded,
            boolean leaf, int row, boolean hasFocus) {
          Node node = extractNode(value);
          setContents(node);
          return panel;
        }
        @Override public Component getTreeCellEditorComponent(
            JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row) {
          Node node = extractNode(value);
          setContents(node);
          this.node = node;
          return panel;
        }
        @Override public Object getCellEditorValue() {
          Object o = super.getCellEditorValue();
          DefaultComboBoxModel<String> m = (DefaultComboBoxModel<String>) comboBox.getModel();
          Node n = new Node(pluginName.getText(), node.getPlugins());
          n.setSelectedPluginIndex(m.getIndexOf(o));
          return n;
        }
        @Override public boolean isCellEditable(final EventObject event) {
          Object source = event.getSource();
          if (!(source instanceof JTree) || !(event instanceof MouseEvent)) {
            return false;
          }
          final JTree tree = (JTree) source;
          final MouseEvent mouseEvent = (MouseEvent) event;
          final TreePath path = tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY());
          if (path == null) {
            return false;
          }
          Object node = path.getLastPathComponent();
          if (node == null || !(node instanceof DefaultMutableTreeNode)) {
            return false;
          }
      
          Rectangle r = tree.getPathBounds(path);
          if (r == null) {
            return false;
          }
          Dimension d = panel.getPreferredSize();
          r.setSize(new Dimension(d.width, r.height));
          if (r.contains(mouseEvent.getX(), mouseEvent.getY())) {
            EventQueue.invokeLater(new Runnable() {
              @Override public void run() {
                Point pt = SwingUtilities.convertPoint(tree, mouseEvent.getPoint(), panel);
                //System.out.println(pt);
                Object o = SwingUtilities.getDeepestComponentAt(panel, pt.x, pt.y);
                if (o instanceof JComboBox) {
                  comboBox.showPopup();
                } else if (o instanceof Component) {
                  Object oo = SwingUtilities.getAncestorOfClass(JComboBox.class, (Component) o);
                  if (oo instanceof JComboBox) {
                    comboBox.showPopup();
                  }
                }
              }
            });
            return true;
          }
          return delegate.isCellEditable(event);
        }
        private static Node extractNode(Object value) {
          if (value instanceof DefaultMutableTreeNode) {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
            Object userObject = node.getUserObject();
            if (userObject instanceof Node) {
              return (Node) userObject;
            }
          }
          return null;
        }
        private void setContents(Node node) {
          if (node == null) {
            return;
          }
          pluginName.setText(node.toString());
          DefaultComboBoxModel<String> model = (DefaultComboBoxModel<String>) comboBox.getModel();
          model.removeAllElements();
          if (node.getPlugins().length > 0) {
            panel.add(comboBox);
            for (String s : node.getPlugins()) {
              model.addElement(s);
            }
            comboBox.setSelectedIndex(node.getSelectedPluginIndex());
          } else {
            panel.remove(comboBox);
          }
        }
      }
      

      这篇关于JTree选择问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-21 13:16