Row and Cell Flashing
Following the pattern established by the
ColorRenderer, you can set up custom renderer/provider pairs to manage fonts, borders, and other effects. Row and cell flashing is no different. In the Broker's Order display, rows flash whenever a price change occurs. A custom
FlashColorRenderer and
FlashProvider class/interface pair can control the flash effects:
public interface FlashProvider {
public boolean isFlashOn(int row, int column);
};
As an example, create a FlashColorRenderer that uses the Decorator pattern just like the ColorRenderer. It should have a constructor that takes two arguments, the first a renderer and the second a FlashProvider:
public class FlashColorRenderer implements TableCellRenderer {
protected TableCellRenderer delegate;
protected FlashProvider provider;
public FlashColorRenderer(TableCellRenderer anotherRenderer,
FlashProvider provider) {
this.delegate = anotherRenderer;
this.provider = provider;
}
...
};
Inside the getTableCellRendererComponent() method, use the FlashProvider to get the flash state of a cell and then flash accordingly:
public Component getTableCellRendererComponent(...) {
// Get the component from the delegate
Component c =
delegate.getTableCellRendererComponent(table, value, isSelected,
hasFocus, row, column);
// Convert view column to model column
int mcol = table.convertColumnIndexToModel(column);
// invert the colours to flash
if (provider.isFlashOn(row, mcol)) {
Color bgrd = c.getForeground();
Color fgrd = c.getBackground();
c.setBackground(bgrd);
c.setForeground(fgrd);
}
return c;
}
Wrap the FlashColorRenderer around the ColorRenderer so that you can use both effectively. Wrapping can continue endlesslyeach layer adding its own specific behavior:
private void registerRendererForClass(JTable table,Class klass) {
// Get Default Renderer from the table
DefaultTableCellRenderer defaultRenderer =
(DefaultTableCellRenderer) table.getDefaultRenderer(klass);
// Wrap the color renderer around the default renderer
TableCellRenderer colorRenderer = new ColorRenderer(defaultRenderer, provider);
// Wrap the flash renderer around the colour renderer
TableCellRenderer flashRenderer = new FlashColorRenderer(colorRenderer,
flashProvider);
// Register our flash renderer with the table
table.setDefaultRenderer(klass, flashRenderer);
}
The final step to get the flashing feature working is to create a TableFlasher class that implements the FlashProvder interface to control the flash state of a cell (see Listing 2). Application code that updates order prices must also notify the TableFlasher of the update (Author's note: SWING is single threaded, so be sure to use the invokeLater() functionality when executing code that accesses UI components outside the Swing event thread.):
TableFlasher flashProvider = new TableFlasher(table);
...
// In a background thread, pick a row
int row = (int) (Math.random() * model.getRowCount());
// Generate a new price
Double price = new Double(Math.random() * 100);
// Update the OrderTableModel
model.updateOrderPrice(row, price);
// Flash the price cell
flashProvider.flashCell(row, 2);
...
With the renderer, provider, and table model in place, a JTable display looks like Figure 3.
 | |
| Figure 3: A Flashing Broker's Order Display |