Solved

Distinguishing components of a JTree node

Posted on 2002-07-01
6
469 Views
Last Modified: 2008-02-01
Is there any way to distinguish between a mouse event on the icon,text, or any other object instaniated in a TreeCellRenderer of a node? I'm trying to assign two different actions to someone clicking on the text of a node and someone clicking on the Icon of a node.
0
Comment
Question by:ashep15
6 Comments
 

Author Comment

by:ashep15
ID: 7122366
I have a DefaultTreeCellRender :

class NodeRenderer extends DefaultTreeCellRenderer {

     private JPanel panel = new JPanel();
     private Component strut = Box.createHorizontalStrut(5);
     private JLabel image = new JLabel(new ImageIcon("../../images/info.jpg"));
     
     
     
     public NodeRenderer(){

          panel.setBackground(UIManager.getColor("Tree.textBackground"));
          setOpaque(false);
          panel.setOpaque(false);
         
          panel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
          panel.add(this);
          panel.add(strut);
          panel.add(image);
     }
     
     public Component getTreeCellRendererComponent(JTree t, Object o, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
     
          DataObj node = (DataObj)o;
          super.getTreeCellRendererComponent(t, o, selected, expanded, leaf, row, hasFocus);
          image.setVisible(node.isLeaf());
         
          return panel;
     }

}


I want to distinguish when someone clicks on the image as opposed to anywhere else on the tree cell.
0
 
LVL 35

Expert Comment

by:girionis
ID: 7122456
 I guess you could use some of the methods defined in the JTree class:

"public Rectangle getRowBounds(int row)"

Returns the Rectangle that the node at the specified row is drawn in.

"public Rectangle getPathBounds(TreePath path)"

Returns the Rectangle that the specified node will be drawn into. Returns null if any component in the path is hidden (under a collapsed parent).

  For more information look at teh API documentation.

   Hope it helps.
0
 
LVL 92

Expert Comment

by:objects
ID: 7123373
Try adding your mouse listener to the components of your renderer.
0
PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

 

Author Comment

by:ashep15
ID: 7124669
Adding a mouseListener doesn't work becuase it's overridden when the tree renders each cell using one instance of JPanel. I've added a mouseListener to my JLabel, but it gets wiped out when rendered. I also tried adding a mouseListener to the NodeRenderer itself to no avail.

I thought if this could be done, it would be by using the coordinates of where on the Rectangle object the mouse clicked occured.
0
 
LVL 7

Accepted Solution

by:
Igor Bazarny earned 500 total points
ID: 7130075
Hi,

Try following code. Does it work for you?

Regards,
Igor Bazarny,
Brainbench MVP for Java 1
-----------------------------------------------------

package ee.swing.tree;

import java.awt.Component;
import java.awt.Rectangle;
import java.awt.event.MouseListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;

public class HitTest{
    public static void main(String[] args){
        new HitTest().run();
    }
   
    public void run(){
        JFrame frame = new JFrame("Hit Test");
        final JTree tree = new JTree(buildModel());
        frame.getContentPane().add(tree);

        TreeCellRenderer renderer = tree.getCellRenderer();
        Component prototype = renderer.getTreeCellRendererComponent(tree,"text",false,false,false,0,false);
        if( prototype instanceof JLabel ){
            JLabel label = (JLabel)prototype;
            final int icon = label.getIcon() == null ? 0 : label.getIcon().getIconWidth();
            final int gap = label.getIconTextGap();
            tree.addMouseListener(new MouseAdapter(){
                public void mouseClicked(MouseEvent event){
                    TreePath path = tree.getClosestPathForLocation(event.getX(), event.getY());
                    Rectangle bounds = tree.getPathBounds(path);
                    if( bounds.contains(event.getPoint()) ){
                        if( event.getX() < bounds.x+icon ){
                            System.out.println("Click on icon");
                        }
                        else if(event.getX() < bounds.x+icon+gap){
                            System.out.println("Click on gap");
                        }
                        else{
                            System.out.println("Click on text");
                        }
                    }
                }
            });
        }

        frame.pack();
        frame.setVisible(true);

    }

    private TreeModel buildModel(){
        DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
        DefaultMutableTreeNode node2 = new DefaultMutableTreeNode("Node 1");
        root.add(node2);
        node2.add(new DefaultMutableTreeNode("Subnode 1-1"));
        node2.add(new DefaultMutableTreeNode("Subnode 1-2"));
        node2.add(new DefaultMutableTreeNode("Subnode 1-3"));
        node2 = new DefaultMutableTreeNode("Node 2");
        root.add(node2);
        node2.add(new DefaultMutableTreeNode("Subnode 2-1"));
        node2.add(new DefaultMutableTreeNode("Subnode 2-2"));
        node2.add(new DefaultMutableTreeNode("Subnode 2-3"));
        node2.add(new DefaultMutableTreeNode("Subnode 2-4"));
        return new DefaultTreeModel(root);
    }
}
0
 

Author Comment

by:ashep15
ID: 7132072
That was it! I just added the mouseClicked function to my existing mouseListener on the JTree. In my NodeRenderer class I added the icon and gap width as constants....

tree.addMouseListener(new MouseAdapter() {
                   
                    public void mousePressed(MouseEvent e) {

                         JTree t = (JTree)e.getSource();
                         int row = t.getRowForLocation(e.getX(), e.getY());
                   
                         if (row != -1){
                              isNewSubset = false;
                              TreePath path = t.getPathForRow(row);
                              DataObj someNode = (DataObj)path.getLastPathComponent();
                             
                              if(someNode.fileIndex > -1){
                                   //display documentView data for the current data entity
                                   DataFile docFile = (DataFile)(fileCollection.elementAt(someNode.fileIndex));
                                   
                                   if(documentView.getText() != docFile.documentation.toString()){
                                        documentView.setText(docFile.documentation.toString());
                                   }
                              } else {
                                   //don't show anything if there is no .ndx file
                                   documentView.setText("");
                              }
                         }
                    }
                   
                    public void mouseClicked(MouseEvent event){
                                             
                         TreePath path = tree.getClosestPathForLocation(event.getX(), event.getY());
          Rectangle bounds = tree.getPathBounds(path);
          if( bounds.contains(event.getPoint()) ){
               if( event.getX() < bounds.x+treeRenderer.icon_size ){
                 System.out.println("Click on icon");
            }
            else if(event.getX() < bounds.x+treeRenderer.icon_size+treeRenderer.gap_size){
              System.out.println("Click on gap");
            }
            else{
              System.out.println("Click on text");
            }
              }
            }
          });
         
          tree.setCellRenderer(treeRenderer);


with treeRenderer being of type of NodeRenderer....


class NodeRenderer extends DefaultTreeCellRenderer {

     private JPanel panel = new JPanel();
     private Component strut = Box.createHorizontalStrut(5);
     private JLabel image = new JLabel(new ImageIcon("../../images/info.jpg"));
     final int icon_size;
  final int gap_size;
     
     
     public NodeRenderer(){

          icon_size = image.getIcon() == null ? 0 : image.getIcon().getIconWidth();
          gap_size = image.getIconTextGap();
          panel.setBackground(UIManager.getColor("Tree.textBackground"));
          setOpaque(false);
          panel.setOpaque(false);
         
          panel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
          panel.add(this);
          panel.add(strut);
          panel.add(image);
     }
     
     public Component getTreeCellRendererComponent(JTree t, Object o, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
     
          DataObj node = (DataObj)o;
          super.getTreeCellRendererComponent(t, o, selected, expanded, leaf, row, hasFocus);
          image.setVisible(node.isLeaf());
         
          return panel;
     }

}
0

Featured Post

Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Checkbox and ListView in Android Layout 4 65
github account with ecipse 1 47
throw exception 21 44
jboss wildfly 10.1 10 94
This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
Introduction This article is the second of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers the basic installation and configuration of the test automation tools used by…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question