Please have a look at the SSCCE. How can I make the non-selected tree nodes' background transparent. At the moment the background of non-selected nodes is white. My cell renderer, however, should paint it non-opaque if it is not selected (and green when selected...what it does). In the end I want non-selected nodes to be just text without background, since the area which is red in the SSCCE has a gradient fill in my application.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
public class SimpleTree extends JFrame
{
public static void main(final String[] args)
{
new SimpleTree();
}
public SimpleTree()
{
super("Creating a Simple JTree");
final Container content = this.getContentPane();
content.setBackground(Color.RED);
final Object[] hierarchy = { "javax.swing", "javax.swing.border", "javax.swing.colorchooser", "javax.swing.event", "javax.swing.filechooser", new Object[] { "javax.swing.plaf", "javax.swing.plaf.basic", "javax.swing.plaf.metal", "javax.swing.plaf.multi" }, "javax.swing.table",
new Object[] { "javax.swing.text", new Object[] { "javax.swing.text.html", "javax.swing.text.html.parser" }, "javax.swing.text.rtf" }, "javax.swing.tree", "javax.swing.undo" };
final DefaultMutableTreeNode root = this.processHierarchy(hierarchy);
final JTree tree = new JTree(root);
tree.setOpaque(false);
tree.setCellRenderer(new MyCellRenderer());
final JScrollPane scroller = new JScrollPane(tree);
scroller.getViewport().setOpaque(false);
scroller.setOpaque(false);
content.add(scroller, BorderLayout.CENTER);
this.setSize(275, 300);
this.setVisible(true);
}
/**
* Small routine that will make node out of the first entry in the array,
* then make nodes out of subsequent entries and make them child nodes of
* the first one. The process is repeated recursively for entries that are
* arrays.
*/
private DefaultMutableTreeNode processHierarchy(final Object[] hierarchy)
{
final DefaultMutableTreeNode node = new DefaultMutableTreeNode(hierarchy[0]);
DefaultMutableTreeNode child;
for (int i = 1; i < hierarchy.length; i++)
{
final Object nodeSpecifier = hierarchy[i];
if (nodeSpecifier instanceof Object[]) // Ie node with children
child = this.processHierarchy((Object[]) nodeSpecifier);
else
child = new DefaultMutableTreeNode(nodeSpecifier); // Ie Leaf
node.add(child);
}
return (node);
}
public class MyCellRenderer extends DefaultTreeCellRenderer
{
@Override
public Component getTreeCellRendererComponent(final JTree tree, final Object value, final boolean sel, final boolean expanded, final boolean leaf, final int row, final boolean hasFocus)
{
final Component ret = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
final DefaultMutableTreeNode node = ((DefaultMutableTreeNode) (value));
this.setText(value.toString());
if (sel)
{
this.setOpaque(true);
this.setBackground(Color.GREEN);
}
else
{
this.setOpaque(false);
this.setBackground(null);
}
return ret;
}
}
}
You should override getBackgroundNonSelectionColor
,getBackgroundSelectionColor
and getBackground
of DefaultTreeCellRenderer
and return appropriate values like so:
public class MyCellRenderer extends DefaultTreeCellRenderer {
@Override
public Color getBackgroundNonSelectionColor() {
return (null);
}
@Override
public Color getBackgroundSelectionColor() {
return Color.GREEN;
}
@Override
public Color getBackground() {
return (null);
}
@Override
public Component getTreeCellRendererComponent(final JTree tree, final Object value, final boolean sel, final boolean expanded, final boolean leaf, final int row, final boolean hasFocus) {
final Component ret = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
final DefaultMutableTreeNode node = ((DefaultMutableTreeNode) (value));
this.setText(value.toString());
return ret;
}
}
which will produce:
Other suggestions:
JFrame
unnecessarily rather create an instance and use that.setSize
on JFrame
rather use a correct LayoutManager
and/or override getPreferredSize()
and call pack()
on JFrame
before setting it visible but after adding all components.JFrame#setDefaultCloseOperation
with either DISPOSE_ON_CLOSE
or EXIT_ON_CLOSE
(DISPOSE_XXX
is usually preferred unless using Timer
s as this will allow main(String[] args)
to continue its execution after Gui has been closed).