I have a JPanel like below
The data in the Transaction table (RIGHT) is generated from a MySQL resultset when the user selects a row in the Plot Table (LEFT). Code below:
tableModelTran.getDataVector().removeAllElements();
if (rs.isBeforeFirst()) {
while (rs.next()) {
java.util.Vector data = new java.util.Vector();
data.add(rs.getString(1));
data.add(rs.getString(2));
data.add(new java.text.SimpleDateFormat("dd/MM/yyyy").format(rs.getDate(3)));
data.add(String.valueOf(new java.text.SimpleDateFormat("MMMM yyyy").format(rs.getDate(3))).toUpperCase());
data.add(rs.getString(4));
data.add(rs.getString(5));
data.add(rs.getString(6));
data.add(rs.getBoolean(7));
tableModelTran.addRow(data);
}
performTotals();
}
I would like to change the colour of the rows to GREEN if the 'Verified' column is ticked and leave uncoloured if it is not. Also, if the user changes the value of the column, the colour should update accordingly. Any and all help is appreciated.
EDIT:
I created a class and added it to my constructor as below:
static class ColorRenderer extends javax.swing.table.DefaultTableCellRenderer {
#Override
public java.awt.Component getTableCellRendererComponent(javax.swing.JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
java.awt.Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (value.equals(true)) {
c.setBackground(java.awt.Color.GREEN);
}
return c;
}
public PlotDetailsWindow() {
initComponents();
....
....
transactionTable.setDefaultRenderer(Boolean.class, new ColorRenderer());
....
....
}
Now whenever I click select a row from the table on the left, if the first value is false, it will not change the colour but if it is true it will change just the 'Verified' column to green and then it doesn't matter if the value is true or false it will always be green. Also, the check boxes turned to true/false now.
I would like to change the colour of the rows to GREEN if the 'Verified' column is ticked
Check out Table Row Rendering.
It shows how to override the prepareRenderer(...) method of JTable to color an entire row based on the data in the row.
The basic structure for overriding this method would be as follows:
JTable table = new JTable(...)
{
public Component prepareRenderer(
TableCellRenderer renderer, int row, int column)
{
Component c = super.prepareRenderer(renderer, row, column);
// add custom rendering here
return c;
}
};
Related
I have a JTable object which displays the content of an Excel table. Once another Excel table is loaded, the differences have to be displayed (so some cells will change its background color, blue for example). This is the structure of my table.
And this is my code:
tblGSM.setDefaultRenderer(Object.class, new CustomTableRenderer(diffs));
CustomTableRenderer.java
public class CustomTableRenderer extends DefaultTableCellRenderer {
private Vector<Diff> diffs;
public PersoTableRenderer(Vector<Diff> diffs){
this.diffs = diffs;
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component c = null;
for (int x = 0; x < diffs.size(); x++){
Diff d = diffs.elementAt(x);
c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
d.getRow(), d.getColumn());
c.setBackground(Color.BLUE);
}
return c;
}}
Diff.java
/*
A class to store the difference of corresponding cells
*/
public class Diff {
private int row, col;
public Diff(int row, int col){
this.row = row;
this.col = col;
}
public Diff(){
this(0,0);
}
public int getRow(){
return row;
}
public int getColumn(){
return col;
}
}
My question is diffs is populated correctly, yet the cells colors which are should be changed are not. Turns out all cells in column 1, 2, ,3, and 7 are changed. What it the solution, then?
From the documentation for DefaultTableCellRenderer (emphasis mine):
However JTable employs a unique mechanism for rendering its cells and therefore requires some slightly modified behavior from its cell renderer. The table class defines a single cell renderer and uses it as a as a rubber-stamp for rendering all cells in the table; it renders the first cell, changes the contents of that cell renderer, shifts the origin to the new location, re-draws it, and so on.
So as you can see, super.getTableCellRendererComponent() may return the same component for multiple cells, and thus your approach will not work.
Note that getTableCellRendererComponent is called once per cell as it is rendering, so in addition to the above caveat, your general approach of setting all renderer components in the table to blue when retrieving a single cell's component is not correct.
Instead you will want to only modify the background color of the component being requested, like (pseudo-code):
c = super.getTableCellRendererComponent(..., row, column)
// also don't forget to translate to model coords
model_row = table.convertRowIndexToModel(row)
model_column = table.convertColumnIndexToModel(column)
if diffs contains model_row,model_column:
c.setBackground(blue)
else
c.setBackground(table.getBackground()) // don't forget to reset
return c
Noting that you also have to reset the background color to its default if its not a "diff" cell, since as the docs state, the components are shared among multiple cells.
By the way, rather than storing the Vector<Diff> in your renderer, you really ought to be using a proper TableModel for this, and then querying the model for information. With a sanely implemented model this will also give you constant-time lookups of whether or not a cell should be blue, rather than having to search through the entire list of Diffs.
PS: Don't forget to translate your renderer/view coordinates to model coordinates when working with your Diffs, assuming they are in model coordinates. View coordinates may not agree with model coordinates if e.g. the table is sorted or the user has rearranged the columns. I've shown this in the above pseudo code.
Here is a complete example showing the use of a table model and per-cell custom backgrounds. You can sort the table and rearrange its columns.
The JTable should allow only a particular, selected row to be edited. The rest of the table should be in the non-editable mode. Upon clicking a an "Edit" button, it should ideally just take into consideration the row number and make it editable.
Override isCellEditable() in your table's TableModel and return true for the desired row:
private static final int DESIRED_ROW = …;
#Override
public boolean isCellEditable(int row, int column) {
return row == DESIRED_ROW;
}
I have this renderer that changes the value of JTable cell.
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
String label = value.toString();
if(label.equals("-")
label = "error";
setValue(label);
return this;
}
In the table's data model, data in row 1, column 2 is "-"
In the JTable GUI, data in at row 1, column 2 is "error"
This code prints the value in data model: "-".
System.out.println(table.getValueAt(1, 2).toString());
Is there any simple way to retrieve the value "error"?
I assume your renderer extends JLabel
((JLabel)table.getCellRenderer(row, column)
.getTableCellRendererComponent(pass all the params here)).getText();
I have a table where each row represents a picture. In the column Path I store its absolute path. The string being kinda long, I would like that when I hover the mouse over the specific cell, a tooltip should pop-up next to the mouse containing the information from the cell.
Just use below code while creation of JTable object.
JTable auditTable = new JTable(){
//Implement table cell tool tips.
public String getToolTipText(MouseEvent e) {
String tip = null;
java.awt.Point p = e.getPoint();
int rowIndex = rowAtPoint(p);
int colIndex = columnAtPoint(p);
try {
tip = getValueAt(rowIndex, colIndex).toString();
} catch (RuntimeException e1) {
//catch null pointer exception if mouse is over an empty line
}
return tip;
}
};
I assume you didn't write a custom CellRenderer for the path but just use the DefaultTableCellRenderer. You should subclass the DefaultTableCellRenderer and set the tooltip in the getTableCellRendererComponent. Then set the renderer for the column.
class PathCellRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(
JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
JLabel c = (JLabel)super.getTableCellRendererComponent( /* params from above (table, value, isSelected, hasFocus, row, column) */ );
// This...
String pathValue = <getYourPathValue>; // Could be value.toString()
c.setToolTipText(pathValue);
// ...OR this probably works in your case:
c.setToolTipText(c.getText());
return c;
}
}
...
pathColumn.setCellRenderer(new PathCellRenderer()); // If your path is of specific class (e.g. java.io.File) you could set the renderer for that type
...
Oracle JTable tutorial on tooltips
You say you store an absolute path in a cell. You are probably using a JLabel for setting absolute path string. Suppose you have a label in your cell, use html tags for expressing tooltip content:
JLabel label = new JLabel("Bla bla");
label.setToolTipText("<html><p>information about cell</p></html>");
setToolTipText() can be used for some other Swing components if you are using something other than JLabel.
I have a JTable and i want a cell (or its row) painted in red when the value entered is higher than a certain value. I'm checking that into a TableModelListener to detect TableChange, so I see no way of colouring the table at the renderer (yet I'm sure it is possible, only it is unknown for me).
I also saw this question but i don't know how to use it.
that job for prepareRendered as you can see here
Following is for single table cell you can extend it for row:
First take table column you want to pint and then add a TableCellRenderer to it as follows:
TableColumnModel columnModel = myTable.getColumnModel();
TableColumn column = columnModel.getColumn(5); // Give column index here
column.setCellRenderer(new MyTableCellRenderer());
Make MyTableCellRendere class which implements TableCellRenderer and extends JLabel(so that we can give a background color to it). It will look something like following:
public class MyTableCellRenderer extends JLabel implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int col) {
JLabel jLabel = (JLabel) value;
setBackground(jLabel.getBackground());
setForeground(UIConstants.black);
setText(jLabel.getText());
return this;
}
}
Now in method where you are listening table cell value change do something like follow:
JLabel label = new JLabel(changedValue);
// check for some condition
label.setBackground(Color.red); // set color based on some condition
myTable.setValueAt(label, 0, 5); // here 0 is rowNumber and 5 is colIndex that should be same used to get tableColumn before.