Tree Cell Renderer Highlight
I have implemented a cutom renderer for my JTree that displays different icons for different types of data. However I cannot get the highlight color to work at all. Before using my custom renderer, the nodes would highlight when selected or being dragged over on and drag and drop operation. Now I cannot get this type of behavior. I attempted using the setBackground() method to set the color according to the "sel" flag that gets passed in to the getTreeCellRendererComponent method. Any advice would be appreciated.
I have implemented a cutom renderer for my JTree that displays different icons for different types of data. However I cannot get the highlight color to work at all. Before using my custom renderer, the nodes would highlight when selected or being dragged over on and drag and drop operation. Now I cannot get this type of behavior. I attempted using the setBackground() method to set the color according to the "sel" flag that gets passed in to the getTreeCellRendererComponent method. Any advice would be appreciated.
Similar Messages
-
How to display multiple JComponents in a tree cell renderer
I have an object in a tree cell renderer and want to display its members(three members) status in a JTree as checkboxes such that each node displays three checkboxex with member-names and a node name. i tried using a JPanel and adding three labels into this panel to be returned for the cell renderer but the GUI fails to paint the node componnents. However on clicking the node the component which isn't visible displays correctly. please Help me out
Since you didn't provide any sample code, it's all about wild guesses on what your problem is. The following code shows the type of program you could have posted :import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;
public class TestTree extends JPanel {
private static class MyCell {
String theCellName;
boolean theFirstField;
boolean theSecondField;
boolean theThirdField;
public MyCell(String aName, boolean firstField, boolean secondField, boolean thirdField) {
theCellName = aName;
theFirstField = firstField;
theSecondField = secondField;
theThirdField = thirdField;
private static class MyTreeCellRenderer extends JPanel implements TreeCellRenderer {
private JLabel theCellNameLabel;
private JCheckBox theFirstCheckBox;
private JCheckBox theSecondCheckBox;
private JCheckBox theThirdCheckBox;
private DefaultTreeCellRenderer theDelegate;
public MyTreeCellRenderer() {
super(new GridLayout(4, 1));
theCellNameLabel = new JLabel();
add(theCellNameLabel);
theFirstCheckBox = new JCheckBox("firstField");
add(theFirstCheckBox);
theSecondCheckBox = new JCheckBox("secondField");
add(theSecondCheckBox);
theThirdCheckBox = new JCheckBox("thirdField");
add(theThirdCheckBox);
theDelegate = new DefaultTreeCellRenderer();
setOpaque(true);
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected,
boolean expanded, boolean leaf, int row, boolean hasFocus) {
if (!(value instanceof DefaultMutableTreeNode)) {
return theDelegate.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
if (!(userObject instanceof MyCell)) {
return theDelegate.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
setBackground(tree.getBackground());
if (selected) {
setBorder(BorderFactory.createLineBorder(Color.BLUE, 2));
} else {
setBorder(BorderFactory.createLineBorder(getBackground(), 2));
MyCell cell = (MyCell)userObject;
theCellNameLabel.setText(cell.theCellName);
theFirstCheckBox.setSelected(cell.theFirstField);
theSecondCheckBox.setSelected(cell.theSecondField);
theThirdCheckBox.setSelected(cell.theThirdField);
return this;
public Component add(Component comp) {
if (comp instanceof JComponent) {
((JComponent)comp).setOpaque(false);
return super.add(comp);
public TestTree() {
super(new BorderLayout());
JTree tree = new JTree(createModel());
tree.setShowsRootHandles(true);
tree.setCellRenderer(new MyTreeCellRenderer());
add(new JScrollPane(tree), BorderLayout.CENTER);
private static final TreeModel createModel() {
DefaultMutableTreeNode root = new DefaultMutableTreeNode(new MyCell("root", true, true, true));
DefaultMutableTreeNode child1 = new DefaultMutableTreeNode(new MyCell("child1", false, true, false));
DefaultMutableTreeNode child2 = new DefaultMutableTreeNode(new MyCell("child2", false, false, true));
root.add(child1);
root.add(child2);
return new DefaultTreeModel(root);
public static void main(String[] args) {
final JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new TestTree());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.setSize(600, 400);
frame.show();
} -
Tree Cell Renderer settings for displaying complete text.
I have a tree model. It is of the form
abc (123.00)
-----def (456.00)
----------ghi (678.00)
But it is displayed like
abc (12...
-----def (45..
----------ghi (67..
I don't want the numbers in the end to be missing. It is a problem for the user to expand them everytime.
I am using, JTree and using my cell renderer, with following properties in
super.getTreeCellRendererComponent(tree, false, X, false, false, row, false);I did try to change it to
super.getTreeCellRendererComponent(tree, false, X, TRUE, false, row, false);but still no success.
My function toString() for tree elements looks like this
double u = "123.00";
String num = String.format("%.2f", u);
return getName() + " (" + num + ")";Can you please suggest possible way around for this?package abc;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.WindowConstants;
import javax.swing.JFrame;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeSelectionModel;
public class NewJPanel extends javax.swing.JPanel implements MouseListener {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new NewJPanel());
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.pack();
frame.setVisible(true);
JTree m_tree;
private JScrollPane myPane;
float multi = 1;
DefaultTreeModel tree = new DefaultTreeModel(new ContainerNode("root"));
DefaultMutableTreeNode parent = (DefaultMutableTreeNode)tree.getRoot();
public NewJPanel() {
super(new BorderLayout());
String util = String.format("%.2f", 123456789012345679801234567980.00);
util = "abc" + " (" + util + ")";
DefaultMutableTreeNode e = new DefaultMutableTreeNode(util);
tree.insertNodeInto(e, parent, 0);
m_tree = new JTree(tree);
m_tree.setEditable(false);
m_tree.setDragEnabled(false);
m_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.CONTIGUOUS_TREE_SELECTION);
m_tree.setAutoscrolls(true);
m_tree.setPreferredSize(new java.awt.Dimension(397, 297));
myPane = new JScrollPane(m_tree);
myPane.setAutoscrolls(true);
myPane.getVerticalScrollBar().setAutoscrolls(true);
add(myPane, BorderLayout.CENTER);
m_tree.addMouseListener(this);
initGUI();
private void initGUI() {
try {
setPreferredSize(new Dimension(400, 300));
} catch (Exception e) {
e.printStackTrace();
public void mouseClicked(MouseEvent e) {
String util = String.format("%f", 6546464642345679801234567980.00 * multi);
util = "abc" + " (" + util + ")";
DefaultMutableTreeNode child = (DefaultMutableTreeNode) parent.getChildAt(0);
child.setUserObject(util);
m_tree.repaint();
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
class ContainerNode extends DefaultMutableTreeNode
private static final long serialVersionUID = 14;
ContainerNode(String s)
{ super(s); }
}Executing this code... clicking in the panel, changes the number.
The new number is displayed as (65464646423456798000000000.000.......
My problem is nearly similar, except that in my code I am using, String.format("%.2f", 6546464642345679801234567980.00 * multi);
and still I get (65...) -
is there anyone who knows or can point me to some explanation
on how to place a background image inside the tree??
i'm trying to place different images for in behind the text
and icons for each state, open and close.
any info would be appreciated.
thanks...You will need to specify an itemRenderer for your tree.
Probably the easiest thing to do is to create an Actionscript
itemRenderer that extends the current TreeItemRenderer. In your
renderer, you can override the updateDisplayList function to allow
for a background image depending on your data.
Here is a skeleton of what your itemRenderer might look like:
package
import mx.controls.treeClasses.*;
import mx.collections.*;
public class MyTreeItemRenderer extends TreeItemRenderer
public function MyTreeItemRenderer()
super();
override protected function
updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(super.data)
//Add your code here to add an image to the background of
this item -
Tree cell renderer shows (...) for long texts
I know that the BasicTreeUI saves a cache but I don't know how to reset this cache, or if there is another solution
Best regards
DekelMy tree is inside jscrollpane.Ok, then I don't understand why your renderer truncates the displayed text.
how can I set the jlabel prefered size to be in the
exact width of the String ?AFAIK, this is the default behavior, i.e. you do not do anything.
(I don't want to see a gap between the label and the end of the
string when a node is selected)Uhm, I have no idea what "gap" you are talking about. I don't see any "gaps" when I select nodes in a JTree. -
JTree cell renderer: how to fill whole row?
hi,
i'm trying to make a tree cell renderer that renders at default height, but fills the horizontal width of the tree (e.g. with a JLabel with a custom background color). I'm working on the theory that in order to do this you need to change the preferred size of the component used to stamp the image at render time.
The problem is that the preferred width then needs to be set to a value that depends on the context of the particular node (e.g. a deeply nested child node will be further to the right than the root node).
I can't seem to find a method to say where the rendering starts though - does anyone know a way?
(also if not then would setting the width to some astronimcal value break anything?)
thanks,
asjfTry this one, it will higlight the background and foreground colors of entire rows.
Oscar
class TableRenderer
extends DefaultTableCellRenderer
implements ListCellRenderer
private boolean focused = true;
private JLabel renderer;
public TableRenderer()
super();
renderer = new JLabel();
renderer.setOpaque(true);
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus)
return renderer;
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column)
renderer =
(JLabel) super.getTableCellRendererComponent(
table,
value,
isSelected,
hasFocus,
row,
column);
/* Make the Labels border empty and indented */
setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
/* This is used to create alternate row colors */
Color bgColor = Color.white;
if (row % 2 == 0)
bgColor = new Color(237, 243, 254);
/* if the table has focus and the row is selected use these colors */
if (table.hasFocus() && table.getSelectedRow() == row)
table.setSelectionForeground(Color.WHITE);
table.setSelectionBackground(new Color(101, 137, 178));
/* if the table has not the focus but the row is selected use these colors */
else if (
table.hasFocus() == false && table.getSelectedRow() == row)
table.setSelectionBackground(new Color(196, 196, 194));
/* if not use the standard color */
else
renderer.setBackground(bgColor);
table.setSelectionForeground(SystemColor.textText);
if (value instanceof ColorData)
ColorData cvalue = (ColorData) value;
setForeground(cvalue.color);
setText(cvalue.data.toString());
/* Set the Labels value */
setText(String.valueOf(value));
return renderer;
} -
Hi
I'm using Java 1.5.0.11
I'm trying to make my own tree cell renderer and editor : the goal is to add to the standard tree cell (icon + uneditable text) an icon to the left, to indicate a certain "state". The state can be change by clicking on it, showxing a JPopupMenu to select a new one.
In my proto, it works well, except that when I change one row, it is redrawn completely blank. I need to click on it again to have it appear.
Any idea on why?
Best regardsTreeSelector. java
package treeselectproto;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.ScrollPaneConstants;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
public class TreeSelector {
protected JTree itsTree;
protected JScrollPane itsScrollPane;
protected Map<Object, State> itsStates=new HashMap<Object, State>();
protected CellRenderer itsRenderer;
protected JPopupMenu itsPopupMenu = new JPopupMenu();
public TreeSelector()
itsTree=new JTree();
itsRenderer=new CellRenderer();
itsTree.setCellRenderer(itsRenderer);
itsTree.setCellEditor(itsRenderer);
itsTree.setEditable(true);
buildScrollPane();
List<State> theStates=State.getPopupStates();
for(State s:theStates)
PopupAction a=new PopupAction(s);
JMenuItem mi=new JMenuItem(a);
itsPopupMenu.add(mi);
private void buildScrollPane() {
itsScrollPane= new JScrollPane(itsTree,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
public JScrollPane getScrollPane() {
return itsScrollPane;
@SuppressWarnings("serial")
private class CellRenderer extends AbstractCellEditor implements TreeCellRenderer, TreeCellEditor
private JPanel itsPanel;
private JLabel itsLabel;
private JButton itsStateBtn;
private BorderLayout itsLayout;
public CellRenderer()
itsPanel=new JPanel();
itsPanel.setLayout(itsLayout=new BorderLayout());
itsPanel.setDoubleBuffered(false);
itsLayout.setVgap(1);
itsLayout.setHgap(1);
itsLabel=new JLabel();
itsLabel.setDoubleBuffered(false);
itsPanel.add(itsLabel,BorderLayout.CENTER);
itsStateBtn=new JButton(new AbstractAction(){
public void actionPerformed(ActionEvent aE) {
showPopup();
itsStateBtn.setBorderPainted(true);
itsStateBtn.setContentAreaFilled(false);
itsStateBtn.setDoubleBuffered(false);
itsPanel.add(itsStateBtn,BorderLayout.WEST);
protected void showPopup() {
itsPopupMenu.show(itsStateBtn, 0, 0);
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus)
TreePath thePath=tree.getPathForRow(row);
itsPanel.setBackground(tree.getBackground());
if(thePath != null)
State theState=getStateForTreePath(thePath);
String ic=theState.getSign();
itsStateBtn.setText(ic);
itsLabel.setText(value.toString());
itsStateBtn.setPreferredSize(null);
itsLabel.setPreferredSize(null);
itsPanel.setBackground( selected? Color.lightGray:tree.getBackground());
itsLayout.invalidateLayout(itsPanel);
return itsPanel;
private Object itsValue;
public Component getTreeCellEditorComponent(JTree aTree, Object aValue, boolean aIsSelected, boolean aExpanded, boolean aLeaf, int aRow) {
// if edting, it has the focus
itsValue=aValue;
return getTreeCellRendererComponent(aTree,aValue,aIsSelected,aExpanded,aLeaf,aRow,true);
public Object getCellEditorValue() {
return itsValue;
public State getStateForTreePath(TreePath thePath) {
State ret=itsStates.get(thePath.getLastPathComponent());
if(ret==null)
ret=State.defaultState();
return ret;
@SuppressWarnings("serial")
private class PopupAction extends AbstractAction
protected State itsState;
public PopupAction(State aState) {
super(aState.getLabel());
itsState = aState;
public void actionPerformed(ActionEvent aE) {
TreePath thePath=itsTree.getEditingPath();
Object theObj=thePath.getLastPathComponent();
itsStates.put(theObj, itsState);
} -
How to make JTree cell renderer respect layout?
Hi,
In the JTree tutorial, the first example TreeDemo shows a simple tree.
http://java.sun.com/docs/books/tutorial/uiswing/components/tree.html
If you grab the frame and make it really thin, you get a horizontal scroll bar in the top pane.
How can I make it so that the tree cells just draw "..." at the end of the string if there is not enough space?
I know the tree cell renderer uses JLabel, but they never seem to show "...", which is one of the best features of a JLabel. Any help is greatly appreciated!Hi,
I got it working, but I also discovered a Java bug that ruins all this effort!
Calculating the node's position & width:
- When child nodes are indented, there is an "L" shaped line drawn... the space to the left of the line's vertical bar is the "leftChildIndent", and the space to the right is the "rightChildIndent". So you add both to get the whole indent.
- I use label.getPreferredSize().width to figure out the node width, since that includes the icon width, the icon-text gap, and the font metrics.
Example program:
- This program models how I want it to look... Always expanded and automatic "..." when the scroll pane is not big enough.
Bug found:
- There is a runnable example below. Just run it and after a couple seconds, move the split pane to the right.
- I use a timer to add a new node every 1 second. The new nodes get stuck being too small, and the original nodes don't have this problem.
// =====================================================
* Adaptation of TreeDemo to allow for tree nodes that show "..."
* when there is not enough space to display the whole label.
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeSelectionModel;
public class TreeDemo extends JPanel {
private JTree tree;
protected class EllipsesTreeCellRenderer implements TreeCellRenderer {
Integer leftIndent = (Integer) UIManager.get("Tree.leftChildIndent");
Integer rightIndent = (Integer) UIManager.get("Tree.rightChildIndent");
int indent = leftIndent.intValue() + rightIndent.intValue();
JLabel label = new JLabel();
DefaultTreeCellRenderer r = new DefaultTreeCellRenderer();
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean selected, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
label.setText("why hello there why hello there why hello there");
if (selected) {
label.setForeground(r.getTextSelectionColor());
label.setBackground(r.getBackgroundSelectionColor());
} else {
label.setForeground(r.getTextNonSelectionColor());
label.setBackground(r.getBackgroundNonSelectionColor());
if (leaf) {
label.setIcon(r.getLeafIcon());
} else if (expanded) {
label.setIcon(r.getOpenIcon());
} else {
label.setIcon(r.getClosedIcon());
label.setComponentOrientation(tree.getComponentOrientation());
int labelWidth = label.getPreferredSize().width;
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
int level = node.getLevel();
if (!tree.isRootVisible()) {
--level;
int indentWidth = indent * level;
int rendererWidth = labelWidth + indentWidth;
// This is zero the first few times getTreeCellRenderer is called
// because the tree is not yet visible.
int maxWidth = (int) tree.getVisibleRect().getWidth();
if (maxWidth > 0) {
if (rendererWidth > maxWidth) {
// figure out how much space "..." will consume.
label.setText(label.getText() + "...");
maxWidth = maxWidth
- (label.getPreferredSize().width - labelWidth);
label.setText(label.getText());
// chop off characters until "..." fits in the visible
// portion.
if (maxWidth > 0) {
while (rendererWidth > maxWidth
&& label.getText().length() > 1) {
label.setText(label.getText().substring(0,
label.getText().length() - 2));
rendererWidth = indentWidth
+ label.getPreferredSize().width;
label.setText(label.getText() + "...");
return label;
public TreeDemo() {
super(new GridLayout(1, 0));
//Create the nodes.
final DefaultMutableTreeNode top = new DefaultMutableTreeNode("");
createNodes(top);
//Create a tree that allows one selection at a time.
tree = new JTree(top);
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setCellRenderer(new EllipsesTreeCellRenderer());
tree.addTreeWillExpandListener(new TreeWillExpandListener() {
public void treeWillExpand(TreeExpansionEvent event) {
public void treeWillCollapse(TreeExpansionEvent event)
throws ExpandVetoException {
throw new ExpandVetoException(event);
for (int i = tree.getRowCount(); i >= 0; i--) {
tree.expandRow(i);
//Create the scroll pane and add the tree to it.
JScrollPane treeView = new JScrollPane(tree);
//Add the scroll panes to a split pane.
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splitPane.setTopComponent(treeView);
splitPane.setBottomComponent(new JLabel(""));
Dimension minimumSize = new Dimension(0, 0);
treeView.setMinimumSize(minimumSize);
splitPane.setDividerLocation(200); //XXX: ignored in some releases
//of Swing. bug 4101306
//workaround for bug 4101306:
//treeView.setPreferredSize(new Dimension(100, 100));
// Makes tree nodes appear cut-off initially.
splitPane.setPreferredSize(new Dimension(500, 300));
//Add the split pane to this panel.
add(splitPane);
// Adds a new node every 1 second
Timer timer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
DefaultMutableTreeNode child = new DefaultMutableTreeNode("");
model.insertNodeInto(child, top, 0);
for (int i = tree.getRowCount(); i >= 0; i--) {
tree.expandRow(i);
timer.start();
private void createNodes(DefaultMutableTreeNode top) {
DefaultMutableTreeNode category = null;
DefaultMutableTreeNode book = null;
category = new DefaultMutableTreeNode("");
top.add(category);
category.add(new DefaultMutableTreeNode(""));
category.add(new DefaultMutableTreeNode(""));
category.add(new DefaultMutableTreeNode(""));
category.add(new DefaultMutableTreeNode(""));
category.add(new DefaultMutableTreeNode(""));
category.add(new DefaultMutableTreeNode(""));
category.add(new DefaultMutableTreeNode(""));
category.add(new DefaultMutableTreeNode(""));
category.add(new DefaultMutableTreeNode(""));
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event-dispatching thread.
private static void createAndShowGUI() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
System.err.println("Couldn't use system look and feel.");
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the window.
JFrame frame = new JFrame("TreeDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
TreeDemo newContentPane = new TreeDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
} -
Problem with addRow and MultiLine Cell renderer
Hi ,
Ive a problem with no solution to me .......
Ive seen in the forum and Ivent found an answer.......
The problem is this:
Ive a JTable with a custom model and I use a custom multiline cell renderer.
(becuse in the real application "way" hasnt static lenght)
When I add the first row all seem to be ok.....
when I try to add more row I obtain :
java.lang.ArrayIndexOutOfBoundsException: 1
at javax.swing.SizeSequence.insertEntries(SizeSequence.java:332)
at javax.swing.JTable.tableRowsInserted(JTable.java:2926)
at javax.swing.JTable.tableChanged(JTable.java:2858)
at javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableMo
del.java:280)
at javax.swing.table.AbstractTableModel.fireTableRowsInserted(AbstractTa
bleModel.java:215)
at TableDemo$MyTableModel.addRow(TableDemo.java:103)
at TableDemo$2.actionPerformed(TableDemo.java:256)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:17
64)
at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(Abstra
ctButton.java:1817)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel
.java:419)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:257
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonL
istener.java:245)
at java.awt.Component.processMouseEvent(Component.java:5134)
at java.awt.Component.processEvent(Component.java:4931)
at java.awt.Container.processEvent(Container.java:1566)
at java.awt.Component.dispatchEventImpl(Component.java:3639)
at java.awt.Container.dispatchEventImpl(Container.java:1623)
at java.awt.Component.dispatchEvent(Component.java:3480)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:3450
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3165)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3095)
at java.awt.Container.dispatchEventImpl(Container.java:1609)
at java.awt.Window.dispatchEventImpl(Window.java:1590)
at java.awt.Component.dispatchEvent(Component.java:3480)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:450)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchTh
read.java:197)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThre
ad.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:144)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:136)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:99)
This seems to be caused by
table.setRowHeight(row,(getPreferredSize().height+2)); (line 164 of my example code)
About the model I think its ok.....but who knows :-(......
Please HELP me in anyway!!!
Example code :
import javax.swing.*;
import javax.swing.table.*;
import java.text.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class TableDemo extends JFrame {
private boolean DEBUG = true;
MyTableModel myModel = new MyTableModel();
MyTable table = new MyTable(myModel);
int i=0;
public TableDemo() {
super("TableDemo");
JButton bottone = new JButton("Aggiungi 1 elemento");
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
//table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
//Add the scroll pane to this window.
getContentPane().add(bottone,BorderLayout.NORTH);
getContentPane().add(scrollPane, BorderLayout.CENTER);
bottone.addActionListener(Add_Action);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
class MyTable extends JTable {
MultiLineCellRenderer multiRenderer=new MultiLineCellRenderer();
MyTable(TableModel tm)
super(tm);
public TableCellRenderer getCellRenderer(int row,int col) {
if (col==1) return multiRenderer;
else return super.getCellRenderer(row,col);
class MyTableModel extends AbstractTableModel {
Vector data=new Vector();
final String[] columnNames = {"Name",
"Way",
"DeadLine (ms)"
public int getColumnCount() { return 3; }
public int getRowCount() { return data.size(); }
public Object getValueAt(int row, int col) {
Vector rowdata=(Vector)data.get(row);
return rowdata.get(col); }
public String getColumnName(int col) {
return columnNames[col];
public void setValueAt (Object value, int row,int col)
//setto i dati della modifica
Vector actrow=(Vector)data.get(row);
actrow.set(col,value);
this.fireTableCellUpdated(row,col);
public Class getColumnClass(int c)
return this.getValueAt(0,c).getClass();
public boolean isCellEditable(int row, int col) {
//Note that the data/cell address is constant,
//no matter where the cell appears onscreen.
if (col == 1)
return false;
else
return true;
public void addRow (String name,ArrayList path,Double dead) {
Vector row =new Vector();
row.add(name);
row.add(path);
row.add(dead);
row.add(name); //!!!Mi tengo questo dato da utilizzare come key per andare a
//prendere il path nella lista dei paths di Project
//(needed as key to retrive data if name in col. 1 is changed)
data.add(row);
//Inspector.inspect(this);
System.out.println ("Before firing Adding row...."+this.getRowCount());
this.fireTableRowsInserted(this.getRowCount(),this.getRowCount());
public void delRow (String namekey)
for (int i=0;i<this.getRowCount();i++)
if (namekey.equals(this.getValueAt(i,3)))
data.remove(i);
this.fireTableRowsDeleted(i,i);
//per uscire dal ciclo
i=this.getRowCount();
public void delAllRows()
int i;
int bound =this.getRowCount();
for (i=0;i<bound;i++)
{data.remove(0);
System.out.println ("Deleting .."+data);
this.fireTableRowsDeleted(0,i);
class MultiLineCellRenderer extends JTextArea implements TableCellRenderer {
private Hashtable rowHeights=new Hashtable();
public MultiLineCellRenderer() {
setEditable(false);
setLineWrap(true);
setWrapStyleWord(true);
//this.setBorder(new Border(
public Component getTableCellRendererComponent(JTable table,Object value, boolean isSelected, boolean hasFocus, int row, int column) {
//System.out.println ("Renderer called"+value.getClass());
if (value instanceof ArrayList) {
String way=new String (value.toString());
setText(way);
TableColumn thiscol=table.getColumn("Way");
//System.out.println ("thiscol :"+thiscol.getPreferredWidth());
//setto il size della JTextarea sulle dimensioni della colonna
//per quanto riguarda il widht e su quelle ottenute da screen per l'height
this.setSize(thiscol.getPreferredWidth(),this.getPreferredSize().height);
// set the table's row height, if necessary
//System.out.println ("Valore getPreferred.height"+getPreferredSize().height);
if (table.getRowHeight(row)!=(this.getPreferredSize().height+2))
{System.out.println ("Setting Row :"+row);
System.out.println ("Dimension"+(getPreferredSize().height+2));
System.out.println ("There are "+table.getRowCount()+"rows in the table ");
if (row<table.getRowCount())
table.setRowHeight(row,(getPreferredSize().height+2));
else
setText("");
return this;
/**Custom JTextField Subclass che permette all'utente di immettere solo numeri
class WholeNumberField extends JTextField {
private Toolkit toolkit;
private NumberFormat integerFormatter;
public WholeNumberField(int value, int columns) {
super(columns);
toolkit = Toolkit.getDefaultToolkit();
integerFormatter = NumberFormat.getNumberInstance(Locale.US);
integerFormatter.setParseIntegerOnly(true);
setValue(value);
public int getValue() {
int retVal = 0;
try {
retVal = integerFormatter.parse(getText()).intValue();
} catch (ParseException e) {
// This should never happen because insertString allows
// only properly formatted data to get in the field.
toolkit.beep();
return retVal;
public void setValue(int value) {
setText(integerFormatter.format(value));
protected Document createDefaultModel() {
return new WholeNumberDocument();
protected class WholeNumberDocument extends PlainDocument {
public void insertString(int offs,
String str,
AttributeSet a)
throws BadLocationException {
char[] source = str.toCharArray();
char[] result = new char[source.length];
int j = 0;
for (int i = 0; i < result.length; i++) {
if (Character.isDigit(source))
result[j++] = source[i];
else {
toolkit.beep();
System.err.println("insertString: " + source[i]);
super.insertString(offs, new String(result, 0, j), a);
ActionListener Add_Action = new ActionListener() {
public void actionPerformed (ActionEvent e)
System.out.println ("Adding");
ArrayList way =new ArrayList();
way.add(new String("Uno"));
way.add(new String("Due"));
way.add(new String("Tre"));
way.add(new String("Quattro"));
myModel.addRow(new String("Nome"+i++),way,new Double(0));
public static void main(String[] args) {
TableDemo frame = new TableDemo();
frame.pack();
frame.setVisible(true);In the addRow method, change the line
this.fireTableRowsInserted(this.getRowCount(),this.getRowCount()); to
this.fireTableRowsInserted(data.size() - 1, data.size() - 1);Sai Pullabhotla -
Event Handling in JTable Custom Cell Renderer
I have a JLabel as a custom cell Renderer for a column. I want to handle mouse click event for the JLabel rendered in the cell.
I tried adding the listener for the label in the custom cell renderer but it is not working. Any ideas how to handle this problem??
Thanks
S.AnandIf you want to handle the selection of a tree node
1) write a class like:
public class TreePaneListener implements TreeSelectionListener {
// TREE SELECTION LISTENER
public void valueChanged(TreeSelectionEvent e) {
JTree tree = (JTree)e.getSource();
DefaultMutableTreeNode node = null;
int count = 0;
boolean doSomething = false;
if(tree.getSelectionCount() > 1) {
TreePath[] selection = tree.getSelectionPaths();
int[] temp = new int[selection.length];
for(int i =0; i < selection.length; i++) {
// Check each node for selection
node = (DefaultMutableTreeNode)selection.getLastPathComponent();
if(node.getLevel()==2) {
// Change this code to take the action desired
doSomething = true;
2) After creating the tree register the listener
TreePaneListener handler = new TreePaneListener();
tree.addTreeSelectionListener(handler); -
Hey ...thanks for you help before....
Another problem..
My Jtree works fine with default Cell Renderer .. but goes to infinite
loop with CustomDefaultRenderer after few minutes...
Any suggestions....
public DynamicTree() {
super(new GridLayout(1,0));
rootNode = new DefaultMutableTreeNode("POSTINGS & SEARCHES");
treeModel = new DefaultTreeModel(rootNode);
treeModel.addTreeModelListener(new MyTreeModelListener());
tree = new JTree(treeModel);
tree.setEditable(false);
tree.getSelectionModel().setSelectionMode
(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setShowsRootHandles(true);
// tree.addMouseListener(ml);
// tree.addKeyListener(kl);
JScrollPane scrollPane = new JScrollPane(tree);
add(scrollPane);
// tree.setCellRenderer();
tree.addTreeSelectionListener(new TreeSelectionListener(){
public void valueChanged(TreeSelectionEvent evt){
System.out.println("Tree's lead selection path is " +
tree.getLeadSelectionPath());
tree.setCellRenderer( new CustomDefaultRenderer());
public class CustomDefaultRenderer extends DefaultTreeCellRenderer {
String suffix = null ;
String prefix = null ;
boolean expired = false;
boolean matched = false ;
PostingHandler pHandler = new PostingHandler();
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);
suffix = (String)value.toString() ;
try {
prefix = value.toString().substring(0,value.toString().indexOf(":") + 1);
suffix = suffix.substring(suffix.indexOf(":")+1,suffix.length());
System.out.println("Prefix:"+prefix +"\tSufix :"+suffix);
}catch (Exception e){System.out.println("Nothing to index yet" + e);}
// value = (Object)suffix;
if(pHandler.newPostingsMatch.contains(prefix)) {
// if(hasFocus){pHandler.removePostingMatch(prefix);}
setBackgroundNonSelectionColor(Color.CYAN);
}else
setBackgroundNonSelectionColor(Color.WHITE);
System.out.println("Other <>values:\tValue" + value.toString() + "\tSEL:"+sel +"\tExpanded:" + "\tLEAF:"+leaf +
"\tRow:" +row + "\tfocus:"+hasFocus );
return this;
public void paintComponent(Graphics g){
System.out.println("Paint is called");
//g.drawLine(0, 0, 100, 100);
if(expired){
g.drawLine(22, 11, 100,11);
g.drawString(suffix, 22,15);
validate();
repaint();
}Figured it out right after this post :)
I had to do the following in my cellrenderer
setBackgroundNonSelectionColor(new Color(0, 0, 0, 0));As a parameter I sent a color object with a alpha level of 0 (completly transparent)... -
JTree as cell renderer for JList
I have an application that requires to display a list of tree-structured data.
So I've used JTree a the cell renderer for the JList, and I can see a list of trees with that data in.
However, the Jtree doesn't respond to Mouse messages, even if I dispatch the to it manually. So the tree is essentially dead.
Does anybody know how to fix this?I'm not sure if they have the same thing for lists though.Yes, it is so - a cellrenderer or celleditor is a component, that is only there during it is used - a cellrenderer is there as long as it needs to paint the contents, a celleditor is there, if an edit-process is invoked and it will get messages as long as the editing process continues - after finishing editing, the component is no longer there - normally the renderer is called after that, to render the new contents into the rectangle of that cell, because the contents in its non-editing state may look other than that from the editor during the editing-state.
greetings Marsian -
Help with JTreeTable custom cell renderer!
Hi.
I've followed diligently the complete TreeTable2 example found on the Sun site. http://java.sun.com/products/jfc/tsc/articles/treetable2/
What I'm trying to do is to add alternate-row shading on the Column(0) of the JTreeTable where the Column class is "TreeTableModel".
so, from the example, I've added the following setCellRenderer declaration to TreeTableExample2.java:
protected JTreeTable createTreeTable() {
JTreeTable treeTable = new JTreeTable(model);
treeTable.getColumnModel().getColumn(1).setCellRenderer
(new IndicatorRenderer());
treeTable.getColumnModel().getColumn(0).setCellRenderer
(new MyTableCellRenderer());Then, I subclass DefaultTableCellRenderer as shown below, in a new class called "MyTableCellRenderer"
import java.awt.Color;
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
public class MyTableCellRenderer extends DefaultTableCellRenderer implements TableCellRenderer
private static final long serialVersionUID = 1L;
public MyTableCellRenderer() {
public Component getTableCellRendererComponent(JTable jtable, Object obj, boolean isSelected, boolean hasFocus, int i, int j)
if (i % 2 == 0 && !isSelected) {
this.setBackground(new Color(214,226,255));
this.setForeground(Color.BLACK);
} else if (isSelected)
this.setBackground(new Color(204, 204, 255));
else {
this.setBackground(Color.white);
//if (obj != null)
this.setValue(obj.toString());
System.out.println("obj: " + obj.toString());
System.out.println("obj type: " + obj.getClass().getName());
return ((Component) (this));
}I've been pulling out whatever few hairs I have left in my sparse scalp to get this working, but it's looking grim thus far.
Here are links to screenshots of my progress, or lack thereof:
Original Working TreeTable II
http://www.pharmalytix.com/original_treetable.jpg
My Not-working Tree Table II w/ Custom Cell Renderer
http://www.pharmalytix.com/customtablecellrenderer_treetable.jpg
thanks again - !!phew! finally got this sucker working. I had to retrieve the default rendererer of my TreeTable's TreeTableModel class column, which is the JTree and then, in its component-form, start mucking about with its stylings. The real black-hole of progress was caused by my brain imploding from not being able to understand that a "Component" was what represented the "thing" whose behaviour I wanted to alter, be it a Jtree node or Jtable cell.
treeTable.getColumnModel().getColumn(0).setCellRenderer(new TableCellRenderer() {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
Component comp = treeTable.getDefaultRenderer(TreeTableModel.class).getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
if (row % 2 == 0 && !isSelected) {
comp.setBackground(new Color(214,226,255));
comp.setForeground(Color.BLACK);
} else
if (isSelected)
comp.setBackground(new Color(204, 204, 255));
else {
comp.setBackground(Color.white);
return comp;
});In all of its ravishing glory:
http://www.pharmalytix.com/alternateshading_treetable.jpg
Edited by: DataHog on Nov 6, 2007 10:21 AM -
JTree custom cell renderer question
When using a custom cell renderer is their anyway to tell the offset of the current node?
For example if you have a tree with the parent node "Parent" that has a few children nodes it will look something like this:
Parent
|----Child 1
|----Child 2
|----Child 3
So the parent would have an offset of zero. I want to know how to get the childrens offset? If this is possible?
What I am trying to accomplish:
I have a JTree as a scrollpane rowHeader. While the main body of the scrollpane is a JTable. I need the tree's nodes to fill the entire width so that it looks like part of the table. I figure the row header width - current node offset should be the width that I will need each node to be. Any help is welcome. Thanks.the renderer tells you the row, the tree can get you a treepath for a row
TreePath getPathForRow(int row)
That can tell you the depth of the node. -
Custom Cell Renderer containing JCheckBox
Hi,
I have a JTable..and I have the following cell renderer
private class MyCellRenderer extends JCheckBox implements TableCellRenderer {
public DeleteCellRenderer() {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setHorizontalAlignment(SwingConstants.CENTER);
setBackground(Color.WHITE);
setSelected(isSelected);
requestFocus(hasFocus);
return this;
// add the renderer to the right column
column = table.getColumnModel().getColumn(0);
column.setCellRenderer(new MyCellRenderer());basically.. when the checkbox is clicked in my cell...the whole cell turns grey (just like a JButton when it is pressed)..i dont want that to happen. Also, the checkbox is not staying selected / deselected.
what am i doing wrong? .... eventually i want to use my own JCheckBox implementation (which will have its own colors).
thanksOk, this is fully working.
One problem was that you were setting the check box based on the isSelected parameter instead of the
value parameter. IsSelected is used to indicate that the row highlight should be drawn.
Also, if you want to change the look of the component inside the square of the check box, you need to change the icon. If you look in com.sun.java.swing.plaf.windows.WindowIcon you can see how the default check box draws itself based on the state of the check box.
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.util.TreeSet;
public class BooleanTable extends JFrame
Object[][] data = {{Boolean.TRUE},{Boolean.TRUE},{Boolean.TRUE},{Boolean.TRUE},{Boolean.TRUE},{Boolean.TRUE}};
String[] header = {"CheckBoxes"};
public BooleanTable()
setDefaultCloseOperation( EXIT_ON_CLOSE );
TableModel model = new AbstractTableModel()
public String getColumnName(int column)
return header[column].toString();
public int getRowCount()
return data.length;
public int getColumnCount()
return header.length;
* Returns <code>Object.class</code> regardless of <code>columnIndex</code>.
* @param columnIndex the column being queried
* @return the Object.class
public Class getColumnClass(int columnIndex)
return( data[0][columnIndex].getClass() );
public Object getValueAt(int row, int col)
return data[row][col];
public boolean isCellEditable(int row, int column)
return true;
public void setValueAt(Object value, int row, int col)
data[row][col] = value;
fireTableCellUpdated(row, col);
JTable table = new JTable(model);
table.setDefaultRenderer( Boolean.class, new MyCellRenderer() );
table.setDefaultEditor( Boolean.class, new MyCellEditor() );
getContentPane().add( new JScrollPane( table ) );
pack();
setLocationRelativeTo( null );
setVisible( true );
public static void main( String[] a )
try
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
catch( Exception e )
new BooleanTable();
private class MyCellRenderer implements TableCellRenderer
protected Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
protected Border focusBorder = UIManager.getBorder("Table.focusCellHighlightBorder");
private JCheckBox checkBox;
public MyCellRenderer()
checkBox = new JCheckBox();
checkBox.setHorizontalAlignment(SwingConstants.CENTER);
checkBox.setBackground( Color.white);
public Component getTableCellRendererComponent(JTable
table, Object value, boolean isSelected, boolean
hasFocus, int row, int column)
checkBox.setSelected( Boolean.valueOf( value.toString() ).booleanValue() );
return checkBox;
private class MyCellEditor extends AbstractCellEditor implements TableCellEditor
JCheckBox checkBox;
public MyCellEditor()
checkBox = new JCheckBox();
checkBox.setHorizontalAlignment(SwingConstants.CENTER);
checkBox.setBackground( Color.white);
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
checkBox.setSelected( Boolean.valueOf( value.toString() ).booleanValue() );
return checkBox;
public Object getCellEditorValue()
return Boolean.valueOf(checkBox.isSelected());
Maybe you are looking for
-
Enhancement of Standard Datasource in LBWE.
Hi, I am enhancing the standard datasource for additional fields from the extract structure in LBWE. I have selected the fields in maintenance and pushed them into the selection criteria (first column), and saved the daatsource change in a request. b
-
Can't find my newly installed Windows Installer 4.5
022614: Windows XP, I've installed the newest version of Windows Installer several times and I can't find it anywhere on my system. It is not listed as a program and it is not listed in the Control Panel Add/Remove list. How am I supposed to find ou
-
Hi To All, Getting an error in Recruitment Module in T-Code PB10 the error is <b>"Feature MASSN is not activated Please activate before you use"</b> the screen of PB10 is Blank nothing is appearing over there. I tried through PB40 also there selected
-
Possible? Edit & Delete SBs on one page
Hi again. I'm having difficulty to have a Delete and Update server behaviour on one page. I have a page displaying all my registered users. This page has a repeat region server behaviour of 30 records. On this page I want to be able to delete users a
-
Hello guys whats are the common tasks carried out in BI SECURITY, Thanks.