I want to color certain rows in JTable based on its value. But my customrenderer is getting called infinite times and the whole table is getting colored instead of certain rows.
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,int row, int column)
{
Component c = render.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
DefaultTableModel model = (DefaultTableModel)table.getModel();
String flag = (String)model.getValueAt(row, 0);
if(flag.equalsIgnoreCase("java"))
{
c.setBackground(new Color(0xE8F2FE)); //light blue
}
return c;
}
The same renderer is used for all cells. Once you change the background of the renderer that background is used for all the cells.
So you need an "else condition" to set the background to the default color. Something like:
else
c.setBackground( table.getBackground() );
You can also check out Table Row Rendering for an alternative approach to highlighting a rows background which can be simpler especially when different types of data are found in each column.
Related
for my Java program basically when the value in column 4 of my JTable is greater than column 3, I want those specific rows to be colored in red and not the other rows.
I have implemented the following code, but for some reason all my rows are getting colored in red rather than just the ones matching the criteria.
table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer(){
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row, int col) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
int Value1= Integer.parseInt(table.getModel().getValueAt(row, 3).toString());
int Value2= Integer.parseInt(table.getModel().getValueAt(row, 4).toString());
if (Value2>=Value1) {
setBackground(Color.red);
}
return this;
}
});
Any suggestions/tips on how to fix this?
A DefaultTableCellRenderer instance uses a template component to render all cells (namely itself, see documentation). Once you set its color, the template will have that color and will be applied to all subsequent cells.
What you need to do is in your logic, set the color to red in the cases you need, and set it to the default background color in all other cases.
if(!isSelected) {
if (Value2>=Value1) {
setBackground(Color.red);
} else {
setBackground(table.getBackground()); // or use another color for another background
}
}
Looking at your code again, I'm noticing you are making an error with regards to model versus view indices. The getTableCellRendererComponent method is called with view indices, yet you are using these to index the model (eg in table.getModel().getValueAt(row, 3)). When your table is sorted, results will be incorrect as model indices and view indices will differ.
If you need to get values from the model, you first need to convert the view indices to model indices. Use JTable.convertRowIndexToModel and JTable.convertColumnIndexToModel to do that. Eg:
int modelRowId = table.convertRowIndexToModel(row);
int Value1= Integer.parseInt(table.getModel().getValueAt(modelRowId, 3).toString());
int Value2= Integer.parseInt(table.getModel().getValueAt(modelRowId, 4).toString());
Take a look at Table Row Rendering which shows how to do this by overriding the prepareRenderer(...) method of the JTable.
Using this approach you don't need a custom renderer for each data type in the table.
I know how to put a String into a JTable cell, and I know how to put an image into a JTable cell. But is it possible to put an image and a String into the SAME JTable cell?
The reason for this is that I have a 'status' column in my JTable, which at the moment contains either a green, amber or red image. And in order to fulfill the design requirement, I need to add some explanatory text alongside each image (so the text next to the green image would be "Online", the text next to the amber image would be "Unknown" and the text next to the red image would be "Offline"). I need to do this in a single column (or what looks/behaves like a single column) rather than two columns.
I have researched this, but found no info at all.
Yes.
You need to use a custom cell renderer. Check out How to use Tables for more details.
You actually have two choices, you could simply set the icon and the text of the cell or you could use the renderers tooltip text instead...
public class IconTextCellRemderer extend DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setText(...);
setIcon(...);
setToolTipText(...);
return this;
}
}
Of course you need to apply the renderer to the column...
TableColumnModel tcm = table.getColumnModel();
tcm.getColumn(x).setCellRenderer(new IconTextCellRemderer());
I have a JTable showing values from a model allowing integer values 0, 1 and 2. The values are shown in a 9 by 9 grid (like a sudoku game board).
My question is: How do I hide the zero values from the GUI?
That is, in the table cells that has a model value of zero, I dont want the GUI to show any value. The model must however contain the zero value due to calculations being done.
I have tried to use a DefaultTableCellRenderer and setting the cell component to invisible by using setVisible(true) (as in this question), but I get no result.
I have managed to use a DefaultTableCellRenderer to toggle any cell's background color depending on the model state (if a cell is considered "negative"). I do want to keep the background color visible.
I am a bit new to java, so maybe this is just an update issue?
Here is my DefaultTableCellRenderer:
private static class GameTableRenderer extends DefaultTableCellRenderer
{
private static final long serialVersionUID = 1L;
#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);
GameModel model = (GameModel) table.getModel();
if(model.isNegative(row, column))
c.setBackground(Color.lightGray);
else
c.setBackground(Color.white);
if(model.getAbsoluteValueAt(row, column) == 0)
c.setVisible(false);
else
c.setVisible(true);
return c;
}
}
The "getAbsoluteValueAt" method returns an integer 0, 1 or 2. The change of background color works perfectly fine.
My model extends AbstractTableModel, and the JTable uses the renderer like this:
table.setDefaultRenderer(int.class, renderer);
I hope this information is enough to explain my problem and the efforts I so far have put in. Please ask for more information and I will provide it.
Thank you in advance. /Fredrik
Or you can use the following:
if(model.getAbsoluteValueAt(row, column) == 0)
c.setForeground(c.getBackground());
else
c.setForeground(Color.BLACK);
Instead of making the component invisible, set its text to the empty string:
if (model.getAbsoluteValueAt(row, column) == 0) {
((JLabel) c).setText("");
}
i try to change the color of fields in a JTable according to their value. I don't want to change any color of the first column but it changes anyway in a buggy way(some fileds are not correctly filed like University and Possible_Reviewer):
My code is as following:
table.setDefaultRenderer(Object.class, new CustomRenderer());
private class CustomRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,boolean hasFocus, int row, int col){
Component comp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
try {
Double val = Double.parseDouble(value.toString());
if(col == 0){
comp.setBackground(Color.white);
} else {
comp.setBackground(changeColor(val));
}
} catch (NumberFormatException e){}
return( comp );
}
private Color changeColor(Double val) {
//returns a Color between red and green depending on val
}
}
The weird thing is that when i use "col == 2" it turns the second column white but the first remains strangely colored.
Anyone an idea?
You should extend JTable class and override this method:
public TableCellRenderer getCellRenderer(int row, int column){}
Otherwise JTable will use the same renderer for each cell in the same column.
EDIT:
Like #Mark Bramnik pointed out, it's better to not instantiate a new TableCellRenderer object for every getCellRenderer call. You could implement a method like the following:
setCellRenderer(int row, int col, TableCellRenderer render)
and store the renderer in the extended JTable itself.
How to Use Tables: Using Custom Renderers mentions this alternative approach: "To specify that cells in a particular column should use a renderer, you use the TableColumn method setCellRenderer()."
Addendum: A benefit of this approach is that the renderer "sticks" to the column if the user drags it to a different position. In this example, replace setDefaultRenderer() with setCellRenderer().
table.getColumnModel().getColumn(DATE_COL).setCellRenderer(new DateRenderer());
I am trying to sort a table using rowsorter.
RowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
cTable.setRowSorter(sorter);
I am using a renderer which extends DefaultTableCellRenderer. I am using the renderer to paint the contents of the cell in some color based on its value.
cTable.setDefaultRenderer(Object.class,new <renderer name>());
eg:
public Component getTableCellRendererComponent(JTable table, Object v,
boolean isSelected, boolean hasFocus, int row, int column)
{
super.getTableCellRendererComponent(table, v, isSelected, hasFocus,
row, column);
int k=table.getValueAt(row,column);
if (k >= 0) this.setForeground(Color.red);
}
Note:This is just a sample code.No real functionality.
when i sort, sorting happens perfectly but the renderer functionality of changing the color is not happening. Has anyone faced this issue earlier?Please help
You need to extend the logic in your renderer to:
if (isSelected) {
this.setForeground(table.getSelectionForeground());
} else if (k >= 0) {
this.setForeground(Color.red);
} else {
this.setForeground(table.getForegroundColor());
}
You may also wish to set the background colour depending on each condition. The reason for doing this is because the DefaultTableCellRenderer acts like a "rubber stamp" which is applied to each cell in turn. If for example, the cell at row 5, column 1 has a value of k >= 0 then you are switching the foreground colour to red for this cell and all subsequent cells. Therefore, it is important to explicitly set it back to the "normal" foreground colour if your check fails.