Monday Feb 22, 2010

Display the tooltip of a JPanel node of a JTree

If you need a JTree composing of nodes each of that consists of icon, text and check box, which Java Swing component will you choose to adopt? JPanel will be the answer. 

Following is a example of such a JTree:

=====================

import java.awt.\*; 
import java.awt.event.\*; 
import java.util.EventObject; 
import javax.swing.\*; 
import javax.swing.tree.\*; 

public class PanelNodeTip { 
    private JScrollPane getContent() { 
        Icon icon = UIManager.getIcon("Tree.closedIcon"); 
        DefaultMutableTreeNode root = 
            new DefaultMutableTreeNode( 
                     new PanelNode("Root", false, icon, "Root Tip")); 
        root.add(new DefaultMutableTreeNode( 
                     new PanelNode("Node 1", false, icon, "Node 1 Tip"))); 
        root.add(new DefaultMutableTreeNode( 
                     new PanelNode("Node 2", true, icon, "Node 2 Tip")));

        JTree tree = new JTree(new DefaultTreeModel(root));

        tree.setEditable(true); 
        tree.setCellRenderer(new PanelNodeRenderer()); 
        tree.setCellEditor(new PanelNodeEditor()); 
        return new JScrollPane(tree); 
    } 

    public static void main(String[] args) { 
        JFrame f = new JFrame(); 
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        f.getContentPane().add(new PanelNodeTip().getContent()); 
        f.setSize(360,300); 
        f.setLocation(200,200); 
        f.setVisible(true); 
    } 


class PanelNode { 
    String name; 
    boolean value; 
    Icon icon; 
    String tip;

    public PanelNode(String s, boolean b, Icon icon, String t) { 
        name = s; 
        value = b; 
        icon = icon; 
    tip = t;
    } 

    public String toString() { 
        return "PanelNode[value: " + value + ", name:" + name + 
               "icon: closedIcon, " + tip + "]"; 
    } 

    public String getTip() {
    return tip;
    }


class PanelNodeRenderer implements TreeCellRenderer { 
    JCheckBox checkBox; 
    JLabel label; 
    JPanel panel; 

    public PanelNodeRenderer() { 
        checkBox = new JCheckBox(); 
        checkBox.setBackground(UIManager.getColor("Tree.background")); 
        checkBox.setBorder(null); 
        label = new JLabel(); 
        label.setFont(UIManager.getFont("Tree.font")); 
        panel = new JPanel(); 
        panel.setOpaque(false); 
        panel.add(checkBox); 
        panel.add(label); 
    } 

    public Component getTreeCellRendererComponent(JTree tree, 
                                                  Object value, 
                                                  boolean selected, 
                                                  boolean expanded, 
                                                  boolean leaf, 
                                                  int row, 
                                                  boolean hasFocus) { 
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)value; 
        PanelNode panelNode = (PanelNode)node.getUserObject(); 
        checkBox.setSelected(panelNode.value); 
        label.setIcon(panelNode.icon); 
        label.setText(panelNode.name);

    label.setToolTipText("ToolTip Test for " + panelNode.getTip());
    tree.setToolTipText("ToolTip Test for " + panelNode.getTip());
        return panel; 
    } 


class PanelNodeEditor extends AbstractCellEditor 
                      implements TreeCellEditor, ActionListener { 
    JCheckBox checkBox; 
    JLabel label;     
    PanelNode panelNode; 
    JComponent editedComponent; 
    JPanel panel; 

    public PanelNodeEditor() { 
        checkBox = new JCheckBox(); 
        checkBox.addActionListener(this); 
        checkBox.setBackground(UIManager.getColor("Tree.background")); 
        checkBox.setBorder(null); 
        label = new JLabel(); 
        label.setFont(UIManager.getFont("Tree.font")); 
        panel = new JPanel(); 
        panel.setOpaque(false); 
        panel.add(checkBox); 
        panel.add(label); 
    } 

    public Component getTreeCellEditorComponent(JTree tree, 
                                                Object value, 
                                                boolean isSelected, 
                                                boolean expanded, 
                                                boolean leaf, 
                                                int row) { 
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)value; 
        panelNode = (PanelNode)node.getUserObject(); 
        checkBox.setSelected(panelNode.value); 
        label.setIcon(panelNode.icon);         
        return panel; 
    } 

    public Object getCellEditorValue() { 
        if(editedComponent == label) 
            panelNode.name = label.getText(); 
        else 
            panelNode.value = checkBox.isSelected(); 
        return panelNode; 
    } 

    public boolean isCellEditable(EventObject anEvent) { 
        if (anEvent instanceof MouseEvent) { 
            return ((MouseEvent)anEvent).getClickCount() >= 1; 
        } 
        return true; 
    } 

    public void actionPerformed(ActionEvent e) { 
        editedComponent = (JComponent)e.getSource(); 
        super.stopCellEditing(); 
    } 
}   

=====================

Compile and execute the program of PanelNodeTip.java with JDK 1.5, you will found that there is no tooltip even if you put the mouse on any of the JTree nodes. What's wrong with it? I did add the lines of

label.setToolTipText("ToolTip Test for " + panelNode.getTip());
    tree.setToolTipText("ToolTip Test for " + panelNode.getTip());

If you execute the program with JDK/JRE 1.6, the tooltips display normally. However they doggedly disappear with JDK/JRE 1.5.

Is it a problem of JDK/JRE 1.5? Maybe. But I need the tooltips. What should I do?

The solution is simple. You just need to replace the line of

JTree tree = new JTree(new DefaultTreeModel(root));

with the following paragraph:

JTree tree = new JTree(new DefaultTreeModel(root)) {
        public String getToolTipText(MouseEvent ev) {
                if (ev == null) {
                      return null;
                }
                TreePath path = this.getPathForLocation(ev.getX(), ev.getY());
                if (path != null) {
                    DefaultMutableTreeNode node =
                        (DefaultMutableTreeNode) path.getLastPathComponent();
                    return ((PanelNode) node.getUserObject()).getTip();
                }
                return null;
           }
    };

    ToolTipManager.sharedInstance().registerComponent(tree);  

Now you can see the tooltips no matter with JVM 1.5 or 1.6.

Do you find what the text in the tooltip is displayed exactly? It is the panelNode.getTip() instead of "ToolTip Test for " + panelNode.getTip(). The lines of label.setToolTipText(...) and tree.setToolTipText(...) could be removed simply.


About

Ye Julia Li

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today