-
Bug
-
Resolution: Not an Issue
-
P4
-
None
-
1.3.0
-
x86
-
windows_2000
Name: boT120536 Date: 04/04/2001
java version "1.3.0_01" (and 1.3.1-beta build 15, per report # 119980)
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0_01)
Java HotSpot(TM) Client VM (build 1.3.0_01, mixed mode)
In our software, we use a JTree as a kind of object browser. Users enter some
of the information about the objects in a table with numbered rows. There may
be quite a few rows and the user may have to look for a particular one by
number. Therefore, we want to number the rows as they appear in the tree. To
do this, we need to find out the index of each row as a child of its parent in
the tree. We have a custom TreeCellRenderer which uses getPathForRow to
accomplish this. Unfortunately, getPathForRow does not work consistently.
To reproduce the problem:
Create a JTree and a custom cell renderer. When you do
getTreeCellRendererComponent in the cell renderer, have it do getPathForRow,
then extract the parent of the object it's trying to render from the path, then
find out the index of the object it's trying to render as a child of that
parent, and add that index to the text of the rendered object.
The getPathForRow function will often not work the first time
getTreeCellRendererComponent is called, so the renderer doesn't generate the
text for the rendered object correctly. The component's size is determined
based on the incorrect text, and this sometimes means that the final (correct)
text of the component gets cut off.
Here is some sample code which demonstrates the problem. (When you open
group1, getPathForRow gets an incorrect path for child1a and child1b; when you
open group2, getPathForRow gets a null path for child2a.)
package JTree;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
public class TreeTester2 extends JFrame {
private JTree tree;
public TreeTester2() {
super();
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root",true);
DefaultMutableTreeNode group1 = new DefaultMutableTreeNode ("group1",true);
DefaultMutableTreeNode group2 = new DefaultMutableTreeNode("group2",true);
DefaultMutableTreeNode child1a = new DefaultMutableTreeNode("child1a",false);
DefaultMutableTreeNode child1b = new DefaultMutableTreeNode("child1b",false);
DefaultMutableTreeNode child2a = new DefaultMutableTreeNode("child2a",false);
root.add(group1);
root.add(group2);
group1.add(child1a);
group1.add(child1b);
group2.add(child2a);
tree = new JTree(root);
tree.setCellRenderer(new BTreeCellRenderer());
Container contentPane = getContentPane();
contentPane.add(tree,BorderLayout.CENTER);
}
public static void main(String args[]) {
TreeTester2 t = new TreeTester2();
t.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
t.pack();
t.show();
}
}
------------------------------------------------------------------------------
package JTree;
import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;
public class BTreeCellRenderer extends DefaultTreeCellRenderer {
public BTreeCellRenderer() {
setOpaque(true);
}
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean selected,
boolean
expanded, boolean leaf, int row, boolean hasFocus) {
//super.getTreeCellRendererComponent(tree,value,selected,expanded,leaf,row,hasFocus);
TreePath path = tree.getPathForRow(row);
System.out.println(getClass() + " value: " + value + " path: "+ path);
try {
Object o = path.getPathComponent(path.getPathCount() -
2);
int index = tree.getModel().getIndexOfChild(o,value);
setText("Number = " + index + " " + value.toString());
} catch(Throwable t) {
System.out.println(getClass() + " throwable: " + t);
setText(value.toString());
}
if(selected) {
setBackground(Color.lightGray);
}
else {
setBackground(Color.white);
}
setForeground(Color.black);
return this;
}
}
(Review ID: 119977)
======================================================================