Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 483
  • Last Modified:

Distinguishing components of a JTree node

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
ashep15
Asked:
ashep15
1 Solution
 
ashep15Author Commented:
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
 
girionisCommented:
 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
 
objectsCommented:
Try adding your mouse listener to the components of your renderer.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
ashep15Author Commented:
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
 
Igor BazarnyCommented:
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
 
ashep15Author Commented:
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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now