Solved

Distinguishing components of a JTree node

Posted on 2002-07-01
6
466 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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
topping3 challenge 14 68
pairs challenge 5 62
what is the difference between "sudo su" and "su - root" 6 101
thymeleaf natural templating vs JSP 2 65
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 last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
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.

943 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

Need Help in Real-Time?

Connect with top rated Experts

1 Experts available now in Live!

Get 1:1 Help Now