Hiding an individual cell in JTable depending on model value - java

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("");
}

Related

Trying to color specific rows of JTable using Custom Renderer, instead all my rows are colored

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.

Customrenderer for JTable is getting called multiple times

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.

Disabling cell outline in JTable

I'm using a JTable to show some data. The user can only select entire rows of the JTable, not individual cells. Here's the code used to allow only rows selection:
jTable1.setCellSelectionEnabled(false);
jTable1.setColumnSelectionEnabled(false);
jTable1.setRowSelectionAllowed(true);
jTable1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
But when a user selects a row the cell in that row gets outlined (first column / last row in the image below):
How Can I disable this outline?
You could simply extend the DefaultTableCellRenderer and pretend, from the UI's side, that the cell isn't "focused".
I removed the border by using the following renderer:
private static class BorderLessTableCellRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 1L;
public Component getTableCellRendererComponent(
final JTable table,
final Object value,
final boolean isSelected,
final boolean hasFocus,
final int row,
final int col) {
final boolean showFocusedCellBorder = false; // change this to see the behavior change
final Component c = super.getTableCellRendererComponent(
table,
value,
isSelected,
showFocusedCellBorder && hasFocus, // shall obviously always evaluate to false in this example
row,
col
);
return c;
}
}
You can set it on your JTable like this:
table.setDefaultRenderer( Object.class, new BorderLessTableCellRenderer() );
or, for Strings:
table.setDefaultRenderer( String.class, new BorderLessTableCellRenderer() );
It's a bit of an hack in that it's simply reusing the original renderer and pretending that the focused/selected cell isn't but it should get you started.
I just found a very simple trick to alter this behaviour. It turns out that cell focusing is an extension of the tables focus. If the table can not be focused on neither can individual cells (though row selections still show up).
All you need is one simple line of code:
jTable1.setFocusable(false);
Here is a picture from a project of mine that implements this same behaviour (Note: I am using windows LookAndFeel)
Regardless of which column you click under the entire row is selected but the cell you clicked is not focused. I hope it helps! :)

JTable trouble changing colors for first column

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());

JTable renderer with sorting

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.

Categories

Resources