Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Jazz Up Your JTables with Reusable Classes-2 : Page 2




Full Text Search: The Key to Better Natural Language Queries for NoSQL in Node.js

Custom Rendering—Row Colors and Highlights
Most of the time you don't have to think about rendering, because Swing handles it all for you. However, to do something different from what Swing offers out of the box you must create specialized pieces of code to implement your specific look and feel. These are called custom renderers.

The first step in creating a custom renderer is to create a class that implements the Swing interface TableCellRenderer. All table renderers must implement this interface. One of its methods, getTableCellRendererComponent(), returns a UI component that you can use to display a value in a table cell. Swing provides a default implementation of the TableCellRenderer interface called DefaultTableCellRenderer. It subclasses JLabel and returns itself (this) from the getTableCellRendererComponent() method. For custom renderers you can either extend DefaultTableCellRenderer or implement your own from scratch. Either way works.

Using the Decorator Pattern
To control the look and feel in a table, a renderer must be able to manipulate the formatting, colors, fonts, and borders of a cell. Most custom renderers are built to solve a particular UI problem, which means they are usually problem specific and need to be rewritten for every display. Another approach is available, however.

Rather than creating a large renderer for each JTable, consider breaking it down. Create a family of small general-purpose, reusable renderers, each responsible for one aspect of a cell's appearance. Use a ColorRenderer to control colors, a FontRenderer to control fonts, and a BorderRenderer to control Borders (see Figure 1).

Figure 1: Decorator Renderers

In addition to being generic and re-usable, renderers can be designed to work with each other using the Decorator pattern. You can implement this technique by creating a constructor on a renderer that takes as an argument another renderer. That is, the renderer is able to wrap an existing renderer (such as the default renderers supplied by the JTable) to take advantage of existing functionality. Take the following snippet:

public class ColorRenderer implements TableCellRenderer { protected TableCellRenderer delegate; public ColorRenderer(TableCellRenderer anotherRenderer) { this.delegate = anotherRenderer; } ... };

The ColorRenderer takes advantage of the functionality that the passed-in renderer (or its "delegate") inside the getTableCellRendererComponent() method provides. This is the method that performs the Swing work associated with painting a cell. It calls the delegate to obtain the UI component and then applies its own color-specific behavior before returning to the caller:

public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Color bgrd = null; Color fgrd = null; if (isSelected) { // Preserve selection colors fgrd = table.getSelectionForeground(); bgrd = table.getSelectionBackground(); } else { // Set our colours fgrd = Color.pink; bgrd = Color.blue; Component c = delegate.getTableCellRendererComponent(table, value, isSelected,
hasFocus, row, column); // Set the component colours c.setBackground(bgrd); c.setForeground(fgrd); return c; }

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date