getTreeCellRendererComponent (defaultTreeCellrenderer )problem

Hi All,

i build a jtree.

i made a mouse event when i click(select) a node i activate

a class that is override the defaultTreeCellrenderer in order to change the icon of this node.

it working fine on the first time .

when i select other node with more childrens below i got exception and that because the getTreeCellRendererComponent run every time you click the node:

publicclass MyMouseListenerextends MouseAdapter{

JTree tree;

Icon SelIcon;

Icon NoTSelIcon;

Color frameColor;

int NumOfNodeUnderselect;

int NodesInTree;

publicstaticint NodeInx=0;

privatestaticboolean[] isChecked;

private DefaultMutableTreeNode[] AllNodes;

privateint Total_node_number;

boolean singleClick =true;

javax.swing.Timer timer;

int mouseDoubleClickThreshold = 200;

private MouseEvent Me;

public MyMouseListener(JTree tree,Icon SelIcon,Icon NoTSelIcon,Color Bacground,int NodesInTree,DefaultMutableTreeNode[] AllNodesArray,boolean[]CheckedArray)

{

// TODO Auto-generated constructor stub

this.tree=tree;

this.SelIcon = SelIcon;

this.NoTSelIcon = NoTSelIcon;

this.frameColor=Bacground;

this.NodesInTree=NodesInTree;

isChecked=CheckedArray;

//init ARRAY OF ALL NODES

Total_node_number=NodesInTree;

this.AllNodes=AllNodesArray;

timer =new javax.swing.Timer(mouseDoubleClickThreshold,new ActionListener()

{

publicvoid actionPerformed(ActionEvent e)

{

if(singleClick)

{

mySingleClick();

}

}

});

timer.setRepeats(false);

}

publicvoid mousePressed(MouseEvent e){

// TODO Auto-generated method stub

//System.out.println("mousePressed");

Me=e;

checkClicks(e);

}

privatevoid mySingleClick()

{

System.out.println("mySingleClick");

int selRow = tree.getRowForLocation(Me.getX(), Me.getY());

//TreePath selPath = tree.getPathForLocation(Me.getX(), Me.getY());

DefaultMutableTreeNode Mousenode = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();

try{

String NodeName = (String)Mousenode.getUserObject();

System.out.println("NodeName="+NodeName);

}

catch(NullPointerException Nop){

System.out.println("NullPointerException");

return;

}

if(selRow != -1)

{

DefaultMutableTreeNode Selnode = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();

String Name = (String)Selnode.getUserObject();

int num_of_nod_below_sel=getNodeCountBelow((TreeModel)tree.getModel() , Selnode,true);

System.out.println("The Number of nodes under "+Name+"="+num_of_nod_below_sel);

IconRenderer SeleIcon=new IconRenderer(SelIcon,NoTSelIcon,frameColor,num_of_nod_below_sel,Total_node_number,AllNodes,isChecked);

tree.setCellRenderer(SeleIcon);

}

}

privatevoid myDoubleClick()

{

System.out.println("myDoubleClick");

}

publicvoid checkClicks(MouseEvent me)

{

if(me.getClickCount() == 1)

{

singleClick =true;

timer.start();

}

else

{

singleClick =false;

myDoubleClick();

}

}

//GETTING NODE NUMBER BELOWS THE SELECTED ONE

publicint getNodeCountBelow(TreeModel model, Object node,boolean includeInitialNode)

{

int n = includeInitialNode ? 1 : 0;

for (int i = 0; i < model.getChildCount(node); i ++)

{

n += getNodeCountBelow(model, model.getChild(node, i),true);

}

return n;

}

}

publicclass IconRendererextends DefaultTreeCellRenderer{

privatestaticfinallong serialVersionUID = 1;

Icon SelectedIcon;

Icon NotSelectedIcon;

Color BackgroundColor;

DefaultMutableTreeNode SelctedNode=null;

int NumOfNodeUnderselect;

int NumOfNodesInTree;

publicstaticint NodeInx=0;

privatestaticboolean[] isChecked;

private DefaultMutableTreeNode[] SelectedNodes;

private DefaultMutableTreeNode[] EntireTreeNodes;

public IconRenderer(Icon SelIcon,Icon NoTSelIcon,Color Bacground,int NumOfSelectNodes,int NodesInTree,DefaultMutableTreeNode[] AllNodesArray,boolean[]CheckedArray)

{

SelectedIcon = SelIcon;

NotSelectedIcon = NoTSelIcon;

BackgroundColor=Bacground;

NumOfNodeUnderselect=NumOfSelectNodes;

NumOfNodesInTree=NodesInTree;

isChecked=CheckedArray;

//init ARRAY OF ALL SelectedNODES

SelectedNodes=new DefaultMutableTreeNode[NumOfNodeUnderselect];

EntireTreeNodes=AllNodesArray;

setBackgroundNonSelectionColor(BackgroundColor);

}

public Component getTreeCellRendererComponent(JTree tree,Object value,boolean sel,boolean expanded,

boolean leaf,int row,boolean hasFocus)

{

super.getTreeCellRendererComponent(tree, value, sel,expanded, leaf, row,hasFocus);

DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;

String NodeName = (String)node.getUserObject();

System.out.println("NodeName="+NodeName);

if(sel)

{

NodeInx=0;

SelctedNode =(DefaultMutableTreeNode) value;

setIcon(SelectedIcon);

int number_ofnodes=getNodeCountBelow((TreeModel)tree.getModel() , node,true);

setCheckNodes();

System.out.println("Number of nodes below the selected="+number_ofnodes);

}

else

{

//in this method we checking if the entire nodes are child of the selected node

for(int i=0;i<NumOfNodesInTree;i++)

{

if(node.equals(EntireTreeNodes[i]) && isChecked[i] )

{

setIcon(SelectedIcon);

break;

}

else

{

setIcon(NotSelectedIcon);

}

}

}

returnthis;

}

// GETTING which nodes are select

publicint getNodeCountBelow(TreeModel model, Object node,boolean includeInitialNode)

{

int n = includeInitialNode ? 1 : 0;

int ChildCount= model.getChildCount(node);

SelectedNodes[NodeInx]=(DefaultMutableTreeNode) node;

NodeInx++;

for (int i = 0; i >< ChildCount; i ++)

{

n += getNodeCountBelow(model, model.getChild(node, i),true);

}

return n;

}

privatevoid setCheckNodes()

{

for(int k=0;k<NumOfNodeUnderselect;k++)

{

for(int i=0;i<NumOfNodesInTree;i++)

{

if(EntireTreeNodes[i].equals(SelectedNodes[k]))

isChecked[i]=true ;

}

}

}

}

my question is specific :

how can i get out from getTreeCellRendererComponent and not each time i made some changes it just to run again inside this class.

Hope i was clear

Thanks>

[12526 byte] By [Gabia] at [2007-11-26 17:47:06]
# 1

Read the tutorial:

http://java.sun.com/docs/books/tutorial/uiswing/components/tree.html#display

You should not set the rendrer when the mouse is clicked, just set it once when you create the tree.

You should use your custom renderer to draw your nodes using your logic, it is called for every node that is being painted.

Rodney_McKaya at 2007-7-9 4:59:24 > top of Java-index,Desktop,Core GUI APIs...
# 2

Thanks for your replay.

i explain why i activate it from mouse.

at the begging i did it with TreeSelectionListener and it was fine except one thing, when i made double click it change my icon too(select the node)

but i was not meant it .

i just want to collapse and expand the node.

because of this i tried from the mouse event activate the renderer.

maybe you have your idea to avoid this thing.

Thanks

Gabia at 2007-7-9 4:59:24 > top of Java-index,Desktop,Core GUI APIs...
# 3
Maybe you can explain again because I didn't understand.I don't see how you can find a reason to explain this.If you need the mouse to change the node just change the node user object and handle it in your custom renderer.
Rodney_McKaya at 2007-7-9 4:59:24 > top of Java-index,Desktop,Core GUI APIs...
# 4

lets assume i want to double click a node with some children.

what im getting right now is:

the node collapse and also checked.

it means it did two operations:

1-it collapse/expand (

2-it checked(select)

and i want to do:

when i double click a node it will only expand/collapse and not select also.

is it clear now?

Gabia at 2007-7-9 4:59:24 > top of Java-index,Desktop,Core GUI APIs...
# 5

What L&F are you using?

This is my solution for Windows L&F.

You can change the extended UI class if you're using another L&F.

tree.setUI(new WindowsTreeUI() {

int mouseDoubleClickThreshold = 300;

boolean singleClick = true;

protected void selectPathForEvent(final TreePath path, MouseEvent event) {

if (isToggleSelectionEvent(event) || isMultiSelectEvent(event))

super.selectPathForEvent(path, event);

else if(SwingUtilities.isLeftMouseButton(event)) {

if(isToggleEvent(event)) {

singleClick = false;

boolean selected = tree.isPathSelected(path);

toggleExpandState(path);

if (!selected)

tree.getSelectionModel().removeSelectionPath(path);

}

else {

if (isLeaf(tree.getRowForPath(path)))

tree.setSelectionPath(path);

else {

singleClick = true;

Timer timer = new Timer(mouseDoubleClickThreshold, new ActionListener() {

public void actionPerformed(ActionEvent e) {

if(singleClick)

tree.setSelectionPath(path);

}

});

timer.setRepeats(false);

timer.start();

}

}

}

}

});

Although I disagree if your concept from a GUI point of view.

I think it's not a desired behavior for a tree.

Rodney_McKaya at 2007-7-9 4:59:24 > top of Java-index,Desktop,Core GUI APIs...