I've been trying for weeks to get a Cell
in a JTable
to flash by changing the background color with RGBtoHSV
, I am able to flash a single row using a method I found searching online but when it comes to multiple rows it does not seem to work.
I've tried creating a custom renderer class but still unable to find a way to have the old value with the new value to flash the cell when oldvalue < newvalue.
All my attempts on getting the oldValue
for the cell has failed so its not in there. I have tried TableCellListener
, a class I found using my googlefu but I had no idea how to implement this into a renderer, although implementing it to a table was successful.
DefaultTableCellRenderer cTaxas = new DefaultTableCellRenderer() {
Color gray = new Color(212, 212, 212);
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
Component cellComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row,
column);
if (table.getValueAt(row, column) != null && !isSelected && (row % 2) == 0) {
cellComponent.setBackground(gray);
cellComponent.setForeground(Color.BLACK);
} else if (table.getValueAt(row, column) != null && !isSelected) {
cellComponent.setBackground(Color.WHITE);
cellComponent.setForeground(Color.BLACK);
}
return cellComponent;
}
};
cTaxas.setHorizontalAlignment(SwingConstants.CENTER);
EDIT:
I'm trying to achieve something like the TableCellListener
.class I have found while searching, but within the DefaultCellRenderer
.
public class TableCellListener implements PropertyChangeListener, Runnable {
private JTable table;
private Action action;
private int row;
private int column;
private Object oldValue;
private Object newValue;
/**
* Create a TableCellListener.
*
* @param table
* the table to be monitored for data changes
* @param action
* the Action to invoke when cell data is changed
*/
public TableCellListener(JTable table, Action action) {
this.table = table;
this.action = action;
this.table.addPropertyChangeListener(this);
}
/**
* Create a TableCellListener with a copy of all the data relevant to the
* change of data for a given cell.
*
* @param row
* the row of the changed cell
* @param column
* the column of the changed cell
* @param oldValue
* the old data of the changed cell
* @param newValue
* the new data of the changed cell
*/
private TableCellListener(JTable table, int row, int column, Object oldValue, Object newValue) {
this.table = table;
this.row = row;
this.column = column;
this.oldValue = oldValue;
this.newValue = newValue;
}
/**
* Get the column that was last edited
*
* @return the column that was edited
*/
public int getColumn() {
return column;
}
/**
* Get the new value in the cell
*
* @return the new value in the cell
*/
public Object getNewValue() {
return newValue;
}
/**
* Get the old value of the cell
*
* @return the old value of the cell
*/
public Object getOldValue() {
return oldValue;
}
/**
* Get the row that was last edited
*
* @return the row that was edited
*/
public int getRow() {
return row;
}
/**
* Get the table of the cell that was changed
*
* @return the table of the cell that was changed
*/
public JTable getTable() {
return table;
}
//
// Implement the PropertyChangeListener interface
//
@Override
public void propertyChange(PropertyChangeEvent e) {
// A cell has started/stopped editing
if ("tableCellEditor".equals(e.getPropertyName())) {
if (table.isEditing())
processEditingStarted();
else
processEditingStopped();
}
}
/*
* Save information of the cell about to be edited
*/
private void processEditingStarted() {
// The invokeLater is necessary because the editing row and editing
// column of the table have not been set when the "tableCellEditor"
// PropertyChangeEvent is fired.
// This results in the "run" method being invoked
SwingUtilities.invokeLater(this);
}
/*
* See above.
*/
@Override
public void run() {
row = table.convertRowIndexToModel(table.getEditingRow());
column = table.convertColumnIndexToModel(table.getEditingColumn());
oldValue = table.getModel().getValueAt(row, column);
newValue = null;
}
/*
* Update the Cell history when necessary
*/
private void processEditingStopped() {
newValue = table.getModel().getValueAt(row, column);
// The data has changed, invoke the supplied Action
if (!newValue.equals(oldValue)) {
// Make a copy of the data in case another cell starts editing
// while processing this change
TableCellListener tcl = new TableCellListener(getTable(), getRow(), getColumn(), getOldValue(),
getNewValue());
ActionEvent event = new ActionEvent(tcl, ActionEvent.ACTION_PERFORMED, "");
action.actionPerformed(event);
}
}
}
I used the celllistener in my JTable like this:
Action action = new AbstractAction() {
public void actionPerformed(ActionEvent e)
{
TableCellListener tcl = (TableCellListener)e.getSource();
System.out.println("Row : " + tcl.getRow());
System.out.println("Column: " + tcl.getColumn());
System.out.println("Old : " + tcl.getOldValue());
System.out.println("New : " + tcl.getNewValue());
}
};
TableCellListener tcl = new TableCellListener(table, action);
I'm trying to get this class working within a JTables Renderer so I can flash the Cell
when the old value is less than the new value that has been pulled from a database.
EDIT2: I'm hoping someone can shed some light as to how I can get the old value within the renderer or a different method of flashing cell tables.