1

我被关于 Java 和 JTree 使用的问题所困扰:

我想逐个节点地创建一个 JTree,其中包含一些 JButtons 组件(或图像,我不介意),如下图所示。它将是同一行中的 3 或 4 个按钮。我成功地做到了。

在此处输入图像描述

但是我被阻止的地方是当我想在每个按钮上添加一个鼠标侦听器来管理他们的工具提示或对他们的操作。事实上,JTree 组件大部分时间用于管理全节点上的操作,而不是在其内部组件上。

我做了一个简短的代码,与我必须使用的真正的大代码进行比较,以快速测试我所说的:

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.tree.*;

import java.awt.event.*;
import java.awt.*;
import java.io.IOException;
import java.net.URL;

public class TreeWithPopup extends JPanel {

    DefaultMutableTreeNode root, node1, node2, node3;

    public TreeWithPopup() {
        MyJTree tree;
        root = new DefaultMutableTreeNode("root", true);
        node1 = new DefaultMutableTreeNode("node 1", true);
        node2 = new DefaultMutableTreeNode("node 2", true);
        node3 = new DefaultMutableTreeNode("node 3", true);
        root.add(node1);
        node1.add(node2);
        root.add(node3);
        setLayout(new BorderLayout());
        tree = new MyJTree(root);
        tree.setCellRenderer(new PCellRenderer());
        add(new JScrollPane((JTree) tree), "Center");
    }

    public Dimension getPreferredSize() {
        return new Dimension(300, 300);
    }

    public static void main(String s[]) {
        JFrame frame = new JFrame("Tree with button");
        TreeWithPopup panel = new TreeWithPopup();
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        frame.setForeground(Color.black);
        frame.setBackground(Color.lightGray);
        frame.getContentPane().add(panel, "Center");
        frame.setSize(panel.getPreferredSize());
        frame.setVisible(true);
        frame.addWindowListener(new WindowCloser());
    }
}

class WindowCloser extends WindowAdapter {
    public void windowClosing(WindowEvent e) {
        Window win = e.getWindow();
        win.setVisible(false);
        System.exit(0);
    }
}

class MyJTree extends JTree implements ActionListener {

    MyJTree(DefaultMutableTreeNode dmtn) {
        super(dmtn);
        addMouseListener(new MouseListener() {
            public void mouseClicked(MouseEvent arg0) {
                System.out.println("JTree.MouseListener");
            }

            public void mouseEntered(MouseEvent arg0) {
                System.out.println("JTree.MouseListener");
            }

            public void mouseExited(MouseEvent arg0) {
                System.out.println("JTree.MouseListener");
            }

            public void mousePressed(MouseEvent arg0) {
                System.out.println("JTree.MouseListener");
            }

            public void mouseReleased(MouseEvent arg0) {
                System.out.println("JTree.MouseListener");
            }
        });

    }

    public void actionPerformed(ActionEvent ae) {
        System.out.println("MyJTree.ActionPerformed");
    }

}

class PCellRenderer extends DefaultTreeCellRenderer {
    public Component getTreeCellRendererComponent(JTree ptree, Object pvalue, boolean psel, boolean pexpanded, boolean pleaf, int prow,
            boolean phasFocus) {
        Box myPanel = new Box(BoxLayout.X_AXIS);

        JButton myButton = new JButton("test");
        Image imgToUse = null;
        Image imgRollOver = null;
        try {
            URL urlIcon = new URL("file:///C:/1.jpg"); // <===== change their the path to icons
            imgToUse = ImageIO.read(urlIcon);
            urlIcon = new URL("file:///C:/2.jpg"); // <===== change their the path to icons
            imgRollOver = ImageIO.read(urlIcon);
        } catch (IOException e) {
            e.printStackTrace();
        }
        myButton.setRolloverIcon(new ImageIcon(imgRollOver));
        myButton.setIcon(new ImageIcon(imgToUse));
        myButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                System.out.println(" detected on ");
            }
        });

        myButton.addMouseListener(new MouseListener() {
            public void mouseClicked(MouseEvent arg0) {
                System.out.println("myButton.MouseListener");
            }

            public void mouseEntered(MouseEvent arg0) {
                System.out.println("myButton.MouseListener");
            }

            public void mouseExited(MouseEvent arg0) {
                System.out.println("myButton.MouseListener");
            }

            public void mousePressed(MouseEvent arg0) {
                System.out.println("myButton.MouseListener");
            }

            public void mouseReleased(MouseEvent arg0) {
                System.out.println("myButton.MouseListener");
            }
        });
        myPanel.add(myButton);

        return myPanel;
    }
}

您只需更改图标路径或将以下两个图标放在“c:/”

在此处输入图像描述

在此处输入图像描述

我还搜索了使用行事件的 x/y 位置,但在渲染后我无法找到按钮的位置。

如果有人能知道如何做到这一点,他可能会很有帮助。

谢谢,至少阅读这个问题;-)

4

1 回答 1

3

Tooltip 支持实际上是由TableCellRenderer直接提供的。你TableCellRenderer的有点糊涂。它扩展自DefaultTreeCellRenderer但不使用它的任何功能,而是创建一个新的BoxJButton并在每次呈现单元格时加载图标......

这将增加您的内存使用量,使您的应用程序变慢...

相反,尝试类似...

class PCellRenderer extends Box implements TreeCellRenderer {

    private Image imgToUse = null;
    private Image imgRollOver = null;

    public PCellRenderer() {
        super(BoxLayout.X_AXIS);

        JButton myButton = new JButton("test");
        try {
            URL urlIcon = new URL("file:///C:/1.jpg"); // <===== change their the path to icons
            imgToUse = ImageIO.read(urlIcon);
            urlIcon = new URL("file:///C:/2.jpg"); // <===== change their the path to icons
            imgRollOver = ImageIO.read(urlIcon);
        } catch (IOException e) {
            e.printStackTrace();
        }
        myButton.setRolloverIcon(new ImageIcon(imgRollOver));
        myButton.setIcon(new ImageIcon(imgToUse));

        add(myButton);
    }

    public Component getTreeCellRendererComponent(JTree ptree, Object pvalue, boolean psel, boolean pexpanded, boolean pleaf, int prow,
            boolean phasFocus) {
        // set the tooltip text here...
        // Maybe change the icon...
        return this;
    }
}

现在,实际上正在做某事...

渲染器是橡皮图章。这实际上不是生命的组成部分。把它们想象成照片。你可以给你的朋友拍照,但你不能和他们互动……同样的事情……

MouseListener您的想法JTree是正确的,实际上JavaDocs实际上对此进行了演示...

public void mousePressed(MouseEvent e) {
    int selRow = tree.getRowForLocation(e.getX(), e.getY());
    TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
    if(selRow != -1) {
        if(e.getClickCount() == 1) {
            mySingleClick(selRow, selPath);
        }
        else if(e.getClickCount() == 2) {
            myDoubleClick(selRow, selPath);
        }
    }
}
于 2013-05-30T07:22:50.000 回答