I've written a custom TreeCellRenderer in order to change a components appearance. Everything works fine, except that setBackground has no effect. The code is definitely executed as the foreground color always changes correctly. Since selected items are rendered in blue and deselected item in white (without having written that code myself), I assume that my changes are overridden by JTree. So what would be the proper way to change the background color?
This is essentially my code:
JTree tree = new JTree();
tree.setCellRenderer(new MyCellRenderer());
///////
public class MyCellRenderer extends DefaultTreeCellRenderer{
#Override
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean isSelected, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
JComponent c = (JComponent) super.getTreeCellRendererComponent(tree, value, isSelected, expanded, leaf, row, hasFocus);
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
MyData data = (MyData)node.getUserObject();
if(data.isX()){
c.setForeground(Color.blue);
c.setBackground(Color.gray);
}
return c;
}
}
Try adding a call to c.setOpaque(true).
Related
As you can see in my pictures:
Before minimize:
After minimize
My renderer takes the last color that have used and paints all my table.
Bellow is my custom renderer class:
public class MyCellRenderer extends DefaultTableCellRenderer {
public static double fstValue;
public static double sndValue;
public MyCellRenderer() { }
public MyCellRenderer(double fstValue, double sndValue) {
this.fstValue = fstValue;
this.sndValue = sndValue;
//System.out.println(this.fstValue+" 2ndvalue"+this.sndValue+" ston constructor");
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if(!isSelected) {
if(compare(this.fstValue,this.sndValue)== 1){
c.setBackground(Color.GREEN);
}else if (compare(this.fstValue,this.sndValue)== -1) {
c.setBackground(Color.red);
}else{
c.setBackground(null);
}
}
return c;
}
}
I m updating the table fast, and I have no problem with that.
But when I resize or minimize or scroll down, the coloring change.
When I minimize and resize, my table change color all, but when I scroll down only the table that I scrolled change color.
I suspect that it has something to do with the repaint or paint method that my renderer calls and have trouble fixing it.
I use threads and every thread calls the code below for the update:
if( home.text().equals(hometmp.toString())==false)
{
MyCellRenderer cellRenderer = new MyCellRenderer(valuehm,valuehmt);
table1.setValueAt(home.text(),i-1,1);
}
You have two calls to super.getTableCellRendererComponent(...). Get rid of the second. Also, there is no need to cast the first call to a label. The method return a Component which has a setBackground() method.
You don't need the synchronized keyword on the method.
I am customizing a JTree so some nodes have checkboxes, using santhosh tekuri's work as a base.
So the idea is writing a custom TreeCellRenderer, which in this case extends JPanel and implements TreeCellRenderer, and then at the method getTreeCellRendererComponent I have to decide for each node if it is receiving a checkbox or not.
I have seen some other examples for a typical JTree to customize each node icon, but they relay on converting each node to a JLabel and getting its text, while here it is a JPanel.
This is how my renderer looks like:
public class CheckTreeCellRenderer extends JPanel implements TreeCellRenderer{
private CheckTreeSelectionModel selectionModel;
private TreeCellRenderer delegate;
private TristateCheckBox checkBox;
protected CheckTreeManager.CheckBoxCustomizer checkBoxCustomer;
public CheckTreeCellRenderer(TreeCellRenderer delegate, CheckTreeSelectionModel selectionModel){
this.delegate = delegate;
this.selectionModel = selectionModel;
this.checkBox = new TristateCheckBox("");
this.checkBox.setOpaque(false);
setLayout(new BorderLayout());
setOpaque(false);
}
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus){
Component renderer = delegate.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
// Inside this if clause, those cells which do not require checkbox will be returned
if({CODE_TO_GET_NODE_TEXT}.startsWith("A")){
return renderer;
}
TreePath path = tree.getPathForRow(row);
if(path != null){
if(checkBoxCustomer != null && !checkBoxCustomer.showCheckBox(path)){
return renderer;
}
if(selectionModel.isPathSelected(path, selectionModel.isDigged())){
checkBox.getTristateModel().setState(TristateState.SELECTED);
}
else{
checkBox.getTristateModel().setState(selectionModel.isDigged() && selectionModel.isPartiallySelected(path) ? TristateState.INDETERMINATE : TristateState.DESELECTED);
}
}
removeAll();
add(checkBox, BorderLayout.WEST);
add(renderer, BorderLayout.CENTER);
return this;
}
}
In this case I want to avoid setting a Tristate checkbox for those cells whose texts starts with "A" as an example. But I can't find a way to get the text from the value argument.
In case it helps, this is how I create the JTree:
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
JTree tree = new JTree(root);
// Add nodes to the tree
DefaultMutableTreeNode friends_node = new DefaultMutableTreeNode("Friends");
friends_node.add(new DefaultMutableTreeNode("Anna"));
friends_node.add(new DefaultMutableTreeNode("Amador"));
friends_node.add(new DefaultMutableTreeNode("Jonas"));
friends_node.add(new DefaultMutableTreeNode("Mike"));
friends_node.add(new DefaultMutableTreeNode("Anthony"));
friends_node.add(new DefaultMutableTreeNode("Maya"));
friends_node.add(new DefaultMutableTreeNode("Pepe Vinyuela"));
root.add(friends_node);
tree.setCellRenderer(renderer = new CheckTreeCellRenderer(tree.getCellRenderer(), new CheckTreeSelectionModel(tree.getModel(), dig)));
Any idea?
If you're using String userObject = "Anna"; new DefaultMutableTreeNode(userObject);, then you might be able to use the DefaultMutableTreeNode#getUserObject() method:
#Override public Component getTreeCellRendererComponent(
JTree tree, Object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
Component renderer = delegate.getTreeCellRendererComponent(
tree, value, selected, expanded, leaf, row, hasFocus);
if (value instanceof DefaultMutableTreeNode) {
Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
// Inside this if clause, those cells which do not require checkbox will be returned
if(userObject instanceof String && ((String) userObject).startsWith("A")){
return renderer;
}
//...
I read a lot of tutorials but no it helps me. I have jTree which works and setForeground works perfectly but when I want to setBackground so jTree is without changes. Can you help me how it should be write. Thanks.
import java.awt.Color;
import java.awt.Component;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
public class UrlNodeRenderer extends DefaultTreeCellRenderer {
public static Icon icon = null;
public UrlNodeRenderer() {
icon = new ImageIcon(getClass().getResource("icon.png"));
}
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);
setOpenIcon(icon);
setClosedIcon(icon);
setLeafIcon(icon);
UrlTreeNode node = (UrlTreeNode) (((DefaultMutableTreeNode) value).getUserObject());
if(node.isContainsPhrase()) {
setForeground(Color.BLUE);
setBackground(Color.PINK); // doesn't works
}
return this;
}
}
You need to use setOpaque(true); on your TreeCellRenderer to change background color. You can add it to constructor:
public UrlNodeRenderer() {
icon = new ImageIcon(getClass().getResource("icon.png"));
setOpaque(true);
}
EDIT:
You need to change background color in false and true cases like next:
private class Renderer extends DefaultTreeCellRenderer{
public Renderer() {
setOpaque(true);
}
#Override
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);
setBackground(selected ? Color.LIGHT_GRAY :
(leaf ? Color.GRAY : tree.getBackground()));
return this;
}
}
In your case:
if(node.isContainsPhrase()) {
setForeground(Color.BLUE);
setBackground(Color.PINK); // doesn't works
}
you set color to all nodes, because you never set color for false case.
I have an application that displays a jTree. Each node in the tree has a boolean field called flagged which indicates whether it requires attention or not from the user.
If the field is true, then I would like it to be highlighted in red, otherwise no highlighting.
What is a good way to accomplish this? Should I extend DefaultTreeCellRenderer? Implement my own custom TreeCellRenderer? Some other method?
Since the custom rendering you want to do is pretty basic, I would just extend DefaultTreeCellRenderer and override its getTreeCellRendererComponent method. You could simply adjust the foreground color on the JLabel that the DefaultTreeCellRenderer uses. Here's a quick example:
tree.setCellRenderer(new DefaultTreeCellRenderer() {
#Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
JLabel label = (JLabel)super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
YourNode node = (YourNode)value;
if (node.isFlagged())
label.setForeground(Color.RED);
return label;
}
});
And the result:
I have a JTree and nodes of it are driven from DefaultMutableTreeNode. Each node can be verify or not.At first the icon of all nodes are the same but, I am going to change the ICON of the verified nodes when I select them and press the verify button.I want to have the ability to click and write on each node so I can not use JLabel to show icons.
I made the following code but it returns NULLException.
class CustomIconRenderer extends DefaultTreeCellRenderer {
ImageIcon defaultIcon;
ImageIcon specialIcon;
ImageIcon closeIcon;
static DefaultTreeModel model;
static myDefaultMutableTreeNode root;
public CustomIconRenderer()
{
openIcon = new ImageIcon(CustomIconRenderer.class.getResource("icons/question.png"));
closeIcon = new ImageIcon(CustomIconRenderer.class.getResource("icons/Target-New-Logo.jpg"));
setLeafIcon(closeIcon);
}
#Override
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);
Object nodeObj = ((DefaultMutableTreeNode)value).getUserObject();
Check_each_nodes_are_verified_change_the_icon();
return this;
}
}
public class myDefaultMutableTreeNode extends DefaultMutableTreeNode{
private static int id=0;
private int nodeid;
private int verify;
private int depth;
}
Millions Thanks.
The DefaultTreeCellRenderer has setters, allowing to set open icon, closed icon and leaf icon. Inside the overridden getTreeCellRendererComponent, set these icons in your derived renderer class how you want and then return that is returned by super.getTreeCellRendererComponent. As you set for every node before you render, you can easily have some different icon for the particular node.