复方JTree的节点让事件底下穿过对象(Compound JTree Node allowing e

2019-06-23 20:50发布

我试图创建一个JTree中的一些节点是包含一个JLabel和一个JButton复合对象。 节点是表示由一个JLabel所示的服务器和端口,将JButton将使用桌面API打开默认的浏览器,然后转到URL。

我已阅读已经下面,并尽可能接近,我可以跟着他们。 节点显示我多么希望它(主要是 - 我可以处理使其更好以后),但是当我尝试点击按钮JTree的是响应事件,而不是按钮。

的Java Swing:添加自定义图形按钮JTree的项目

http://www.java2s.com/Code/Java/Swing-JFC/TreeCellRenderer.htm

https://stackoverflow.com/a/3769158/1344282

我需要知道如何让事件通过的JTree,使他们由对象(S)处理下 - 将JButton或JLabel的。

这里是我的TreeCellEditor:

public class UrlValidationCellEditor extends DefaultTreeCellEditor
{
    public UrlValidationCellEditor(JTree tree, DefaultTreeCellRenderer renderer)
    {
        super(tree, renderer);
    }

    @Override
    public Component getTreeCellEditorComponent(JTree tree, Object value,
            boolean isSelected, boolean expanded, boolean leaf, int row)
    {
        return renderer.getTreeCellRendererComponent(tree, value, true, expanded, leaf, row, true);
    }

    @Override
    public boolean isCellEditable(EventObject anEvent)
    {
        return true; // Or make this conditional depending on the node
    }
}

这里是TreeCellRenderer的:

public class UrlValidationRenderer extends DefaultTreeCellRenderer implements TreeCellRenderer
{
    JLabel titleLabel;
    UrlGoButton goButton;

    JPanel renderer;

    DefaultTreeCellRenderer defaultRenderer = new DefaultTreeCellRenderer();

    public UrlValidationRenderer()
    {
        renderer = new JPanel(new GridLayout(1, 2));
        titleLabel = new JLabel(" ");
        titleLabel.setForeground(Color.blue);
        renderer.add(titleLabel);
        goButton = new UrlGoButton();
        renderer.add(goButton);
        renderer.setBorder(BorderFactory.createLineBorder(Color.black));
        backgroundSelectionColor = defaultRenderer
            .getBackgroundSelectionColor();
        backgroundNonSelectionColor = defaultRenderer
            .getBackgroundNonSelectionColor();
    }

    @Override
    public Component getTreeCellRendererComponent(JTree tree, Object value,
      boolean selected, boolean expanded, boolean leaf, int row,
      boolean hasFocus)
    {
        Component returnValue = null;
        if ((value != null) && (value instanceof DefaultMutableTreeNode))
        {
          Object userObject = ((DefaultMutableTreeNode) value)
              .getUserObject();
          if (userObject instanceof UrlValidation)
          {
                UrlValidation validationResult = (UrlValidation) userObject;
                titleLabel.setText(validationResult.getServer()+":"+validationResult.getPort());
                goButton.setUrl(validationResult.getUrl());

                if (selected) {
                  renderer.setBackground(backgroundSelectionColor);
                } else {
                  renderer.setBackground(backgroundNonSelectionColor);
                }
                renderer.setEnabled(tree.isEnabled());
                returnValue = renderer;
          }
        }
        if (returnValue == null)
        {
          returnValue = defaultRenderer.getTreeCellRendererComponent(tree,
              value, selected, expanded, leaf, row, hasFocus);
        }
        return returnValue;
    }

}

我将不胜感激任何见解或建议。 谢谢!

Answer 1:

该渲染器不工作这条路。 它们被用作橡皮图章,这意味着有真正的渲染器只有一个实例是涂遍为JList的是画的地方。 因此,它不能处理鼠标输入,对象是不是真的存在 - 他们只是画。

为了通过鼠标事件对象的下面,你需要实现一个单元格编辑器。 有时,编辑器看起来比呈现不同(字符串渲染器的标签,编辑是文本框,例如)。 按照这一逻辑,编辑器必须使用组件的另一个实例来实现。

现在,你要呈现按钮,并将其用于操纵(即编辑)。 然后,编辑必须是一个JButton的另一个实例,从演示与众不同。 实现按钮渲染器是容易的,但棘手的部分是实现是作为一个编辑器。 您需要延长AbstractCellEditor和实施的TreeCellEditor 和ActionListener的 。 该按钮然后编辑类的字段。 在编辑器类的构造函数,你初始化按钮,将添加为新的动作侦听器的按钮 。 在getTreeCellEditorComponent方法,你可以返回按钮。 在actionPerformed,你叫你需要做的按下按钮,然后调用stopCellEditing()的任何代码。

这样,它为我工作。

我做了演示一个字符串树使用一个SSCCE

public class Start
{
    public static class ButtonCellEditor extends AbstractCellEditor implements TreeCellEditor, ActionListener, MouseListener
    {
        private JButton button;
        private JLabel label;
        private JPanel panel;
        private Object value;

        public ButtonCellEditor(){
            panel = new JPanel(new BorderLayout());
            button = new JButton("Press me!");
            button.addActionListener(this);
            label = new JLabel();
            label.addMouseListener(this);
            panel.add(button, BorderLayout.EAST);
            panel.add(label);
        }

        @Override public Object getCellEditorValue(){
            return value.toString();
        }

        @Override public void actionPerformed(ActionEvent e){
            String val = value.toString();
            System.out.println("Pressed: " + val);
            stopCellEditing();
        }

        @Override public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row){
            this.value = value;
            label.setText(value.toString());
            return panel;
        }

        @Override public void mouseClicked(MouseEvent e){
        }

        @Override public void mousePressed(MouseEvent e){
            String val = value.toString();
            System.out.println("Clicked: " + val);
            stopCellEditing();
        }

        @Override public void mouseReleased(MouseEvent e){
        }

        @Override public void mouseEntered(MouseEvent e){
        }

        @Override public void mouseExited(MouseEvent e){
        }

    }

    public static class ButtonCellRenderer extends JPanel implements TreeCellRenderer
    {
        JButton button;
        JLabel label;

        ButtonCellRenderer(){
            super(new BorderLayout());
            button = new JButton("Press me!");
            label = new JLabel();
            add(button, BorderLayout.EAST);
            add(label);
        }

        @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus){
            label.setText(value.toString());
            return this;
        }

    }

    public static void main(String[] args){
        JTree tree = new JTree();
        tree.setEditable(true);
        tree.setCellRenderer(new ButtonCellRenderer());
        tree.setCellEditor(new ButtonCellEditor());

        JFrame test = new JFrame();
        test.add(new JScrollPane(tree));
        test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        test.setSize(500, 500);
        test.setLocationRelativeTo(null);
        test.setVisible(true);
    }
}


Answer 2:

该节点应该有2份的标签和一个按钮。 当用户点击该标签然后关于节点一些详细的信息应当出现在GUI的不同部分。 当用户点击该按钮,应该产生一个浏览器窗口中打开。 ..

不要那样做。 取而代之的是,刚刚在树的标签。 将按钮添加到显示“有关节点的详细信息”相同的GUI。



文章来源: Compound JTree Node allowing events to pass through to objects underneath