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