当前位置: 首页 > 面试题库 >

复合JTree节点,允许事件传递到下面的对象

斜高翰
2023-03-14
问题内容

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

我已经阅读了以下内容,并已尽可能详细地关注它们。将显示节点的显示方式(主要是-
我可以稍后再对其进行改进),但是当我尝试单击按钮时,JTree会响应事件,而不是按钮。

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

我需要知道如何允许事件通过JTree,以便它们由下面的对象-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;
    }

}

我将不胜感激或提出任何建议。谢谢!


问题答案:

渲染器无法以这种方式工作。它们被用作橡皮图章,这意味着在绘制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);
    }
}


 类似资料:
  • 我在这里使用这个示例代码创建一个JTree,其中所有的叶子都有一个复选框。我遇到的问题是,我还需要能够选择节点对象,而不必勾选复选框。在我的用例中,勾选复选框将使某些内容可见或隐藏,但选择节点将允许在UI的单独部分编辑对象。最好的方法是什么?是否可以检测何时单击复选框的“框”部分,或者是否选中节点? 我看到的另一个错误是,当文件夹有子元素时,文件夹左侧的指示器正确显示文件夹已打开: 但是如果'文件

  • 我正在尝试使用ploly python创建仪表板。需要为饼图的日期选择创建下拉列表。所有数据都来自. csv文件。 期望:饼图中显示的数据基于所选日期。 数据: 在此处输入图像描述 代码: 然而,当选择日期时,它一直显示错误信息。< br >错误消息:“只允许将类似列表的对象传递给< code>isin(),您传递了< code>[str]” 并且数据不会基于所选日期显示。 有人知道原因和解决方法

  • 我试图得到以下每个元素使用 inspect元素的输出如下。 但是它失败了,并抛出下面的错误。 另外,我如何遍历每个类?每个类都包含子部分,我想在进入下一个类之前进一步单独处理这些子部分。

  • 我试图在弹出组件和JMenuItem组件的click action事件中向JTree动态添加节点。我右键单击节点组件并添加另一个节点。添加节点适用于叶节点,但不适用于非叶节点。我不知道代码有什么问题。似乎添加了节点,但Gui没有更新。 平台:Windows 7 Java Java版本“1.7.0\u 17”Java(TM)SE运行时环境(build 1.7.0\u 17-b02)Java HotS

  • 问题内容: 我在创建JTree时遇到困难,该JTree允许通过将节点拖放到JTree中进行重组。看来应该比较简单。我在网上看过示例,但似乎无法在自己的代码中实现它。 例如,sun提供的这种功能允许在不同组件之间拖动到树中,但不能从树本身内部拖动。 而且我也发现了这一点,它允许您将文本拖到JTree中,但不能拖到树中。 任何参考或建议将是巨大的。谢谢 问题答案: 之前没有做过,但是谷歌快速搜索在这里

  • 我试图将JTree节点可视化为JButton,我已经尝试使用JButton对象创建一个默认可变树节点,并将其添加到JTree中: 这些只显示带有黑色参数的错误行。 搜索网络我只发现我需要一个类,但没有一个结果显示如何使用它。 是否有一些教程可以让我找到一些示例来完成任务?