JTree节点可更改工具提示

时间:2012-06-18 11:43:25

标签: java swing tooltip jtree renderer

我有一个JTree填充了一些(自定义)节点。我有一个类是DefaultTreeCellRenderer的子类,使用“MyTreeCellRenderer”我可以为树中的每个节点设置工具提示。它工作正常:JTree已填充,单元格渲染器已设置,所有添加的节点都有工具提示。 问题是我不知道如何在已经填充的树中更改某个节点的工具提示...怎么做?有没有办法在JTree中为一个节点“重新创建”单元格渲染器?

2 个答案:

答案 0 :(得分:6)

我做到了!而不是使用扩展的CellRenderer我使用树的“getTooltipText”方法(我扩展了树)。这样我就能够根据鼠标指针在其上控制工具提示的文本。

@Override
public String getToolTipText(MouseEvent evt) {
    if (getRowForLocation(evt.getX(), evt.getY()) == -1)
      return null;
    TreePath curPath = getPathForLocation(evt.getX(), evt.getY());
    TreeNode node = (TreeNode)curPath.getLastPathComponent();
    if(something)
        return "Empty";

    if(something_else)
        return "Not empty";

    return null;
  }

在工具提示呈现之前,您还需要告诉工具提示管理器您的树:

ToolTipManager.sharedInstance().registerComponent(myTree);

答案 1 :(得分:5)

根据我对您的问题的理解,您希望触发树中特定节点的渲染。这应该通过TreeModel执行以触发正确的事件(即treeNodesChanged)。 DefaultTreeModel为此目的提供了一种实用方法:nodeChanged

然而,JTree中的工具提示由JTree通过重新调用TreeCellRenderer主动处理,这意味着不需要为工具提示进行任何更改。每次需要显示工具提示时,都会执行给定节点的渲染。请参阅此示例,该示例不断更新其工具提示(只需在树的节点周围移动鼠标)。

import java.awt.Component;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;

public class TestTree {

    public class MyTreeCellRenderer extends DefaultTreeCellRenderer {

        private int rendering = 0;

        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row,
                boolean hasFocus) {
            Component cell = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
            if (cell instanceof JComponent) {
                ((JComponent) cell).setToolTipText("Hello " + rendering++);
                if (value instanceof Node && cell instanceof JLabel) {
                    ((JLabel) cell).setText(((Node) value).name);
                }
            }
            return cell;
        }
    }

    private JFrame f;
    private JTree tree;

    protected void initUI() {
        Node root = new Node("Root");
        fillTree(root, 5, "Some tree label");
        DefaultTreeModel model = new DefaultTreeModel(root);

        tree = new JTree(model);
        ToolTipManager.sharedInstance().registerComponent(tree);
        tree.setCellRenderer(new MyTreeCellRenderer());
        f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLocationRelativeTo(null);
        f.add(new JScrollPane(tree));
        f.pack();
        f.setVisible(true);

    }

    public void fillTree(Node parent, int level, String label) {
        for (int i = 0; i < 5; i++) {
            Node node = new Node(label + " " + i);
            parent.addNode(node);
            if (level > 0) {
                fillTree(node, level - 1, label);
            }
        }

    }

    public class Node implements TreeNode {

        private Node parent;
        private List<Node> children;
        private String name;

        public Node(String name) {
            this.name = name;
            this.children = new ArrayList<TestTree.Node>();
        }

        public void addNode(Node child) {
            children.add(child);
            child.parent = this;
        }

        @Override
        public TreeNode getChildAt(int childIndex) {
            return children.get(childIndex);
        }

        @Override
        public int getChildCount() {
            return children.size();
        }

        @Override
        public Node getParent() {
            return parent;
        }

        @Override
        public int getIndex(TreeNode node) {
            return children.indexOf(node);
        }

        @Override
        public boolean getAllowsChildren() {
            return true;
        }

        @Override
        public boolean isLeaf() {
            return children.size() == 0;
        }

        @Override
        public Enumeration<Node> children() {
            return Collections.enumeration(children);
        }

    }

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestTree().initUI();
            }
        });
    }

}