I'd like to color elements in a JTree. However, simply adding a background color only to the label looks kind of strange. Particularly if more than one node is selected, the resulting shape looks ragged and distracting.
Is there a way to make the background extend the whole width of the tree element, so that the whole row gets colored? Either starting at the left border or starting at the beginning of the label, but definitely extending till the right border of the component?
Here is a small self-contained demo, based on this question.
import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;
public class SO26724913 {
public static void main(String[] args) {
DefaultMutableTreeNode a = new DefaultMutableTreeNode("a");
DefaultMutableTreeNode b = new DefaultMutableTreeNode("b");
DefaultMutableTreeNode c = new DefaultMutableTreeNode("c");
a.add(b);
a.add(c);
final JTree tree = new JTree(a);
tree.setCellRenderer(new DefaultTreeCellRenderer() {
@Override
public Component getTreeCellRendererComponent
(JTree tree, Object value, boolean selected,
boolean expanded, boolean leaf, int row, boolean focus)
{
JComponent c = (JComponent)
super.getTreeCellRendererComponent
(tree, value, selected, expanded, leaf, row, focus);
DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
String data = (String)node.getUserObject();
if ("b".equals(data)) {
c.setBackground(Color.RED);
c.setOpaque(true);
}
else {
c.setBackground(null);
c.setOpaque(false);
}
return c;
}
});
JFrame frm = new JFrame();
frm.getContentPane().add(tree);
frm.setSize(200, 200);
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.setVisible(true);
}
}
This is what the code currently generates.
I'd prefer either this
or this.
You might be able to override the paintComponent(Graphics)
method of JTree
to paint selection rectangles directly:
import java.awt.*;
import java.awt.event.*;
import java.util.Arrays;
import javax.swing.*;
import javax.swing.tree.*;
public class ColorTreeTest {
private static final Color SELC = Color.RED;
public JComponent makeUI() {
FocusListener fl = new FocusListener() {
@Override public void focusGained(FocusEvent e) {
e.getComponent().repaint();
}
@Override public void focusLost(FocusEvent e) {
e.getComponent().repaint();
}
};
DefaultTreeCellRenderer r = new DefaultTreeCellRenderer() {
@Override public Component getTreeCellRendererComponent(
JTree tree, Object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
JLabel l = (JLabel) super.getTreeCellRendererComponent(
tree, value, selected, expanded, leaf, row, false);
l.setBackground(selected ? Color.RED
: tree.getBackground());
l.setOpaque(true);
return l;
}
};
JPanel p = new JPanel(new GridLayout(1, 2));
for (JTree t : Arrays.asList(new ColorTree1(), new ColorTree2())) {
t.addFocusListener(fl);
t.setCellRenderer(r);
t.setOpaque(false);
p.add(new JScrollPane(t));
}
return p;
}
static class ColorTree1 extends JTree {
@Override public void paintComponent(Graphics g) {
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
if (getSelectionCount() > 0) {
g.setColor(SELC);
for (int i : getSelectionRows()) {
Rectangle r = getRowBounds(i);
g.fillRect(r.x, r.y, getWidth() - r.x, r.height);
}
}
super.paintComponent(g);
if (getLeadSelectionPath() != null) {
Rectangle r = getRowBounds(getRowForPath(getLeadSelectionPath()));
g.setColor(hasFocus() ? SELC.darker() : SELC);
g.drawRect(r.x, r.y, getWidth() - r.x - 1, r.height - 1);
}
}
}
static class ColorTree2 extends JTree {
private static final Color SELC = Color.RED;
@Override public void paintComponent(Graphics g) {
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
if (getSelectionCount() > 0) {
g.setColor(SELC);
//@see http://ateraimemo.com/Swing/TreeRowSelection.html
for (int i : getSelectionRows()) {
Rectangle r = getRowBounds(i);
g.fillRect(0, r.y, getWidth(), r.height);
}
}
super.paintComponent(g);
if (getLeadSelectionPath() != null) {
Rectangle r = getRowBounds(getRowForPath(getLeadSelectionPath()));
g.setColor(hasFocus() ? SELC.darker() : SELC);
g.drawRect(0, r.y, getWidth() - 1, r.height - 1);
}
}
}
public static void main(String... args) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new ColorTreeTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With