JList, JTable and JTree ("receivers") all employ CellRenderer components to paint their cells. Certain default components are available, but you can define your own. Each time the receiver needs to paint a (row, cell, node) it asks the renderer for a component (a subclass of java.awt.Component) configured in a certain way, emplaces it with setBounds(), and "stamps" it in place with paint().
Remember, what "implementing an interface" means is that a concrete class provides code for all the methods declared in the interface. Since a renderer subclasses some component (sensibly a Swing component, most frequently JLabel), the only new code you need to write is an implementation for the single getXXXCellRendererComponent() method of the XXXCellRenderer interface.
In the example below, a JList displays TrekData objects (defined elsewhere), using a custom ListCellRenderer that extends JLabel. When the JList (automatically, repeatedly) calls getListCellRendererComponent() on the (anonymous, internal) renderer, it passes five arguments: a reference to itself, the TrekData object being rendered, the index of the row, whether the row is selected, and whether the row has mouse focus. The renderer (JLabel subclass) can use any or all of these arguments to configure itself. In this case, it retrieves a symbolic int value from the passed-in TrekData that defines the nationality of a starship, and uses it to set the JLabel's text and icon. It also reads the isSelected argument to see if the "reverse video" selection effect needs to be painted, via setBackground().
The TableCellRenderer and TreeCellRenderer operate in the same way, except that their receivers know how to paint table cells and collapsible tree nodes, respectively.
If you want to select rows with a "reverse video" effect, you first have to setOpaque(true) the renderer component. Swing components are transparent by default (i.e., the background color is transparent), so if you don't, the color of the underlying receiver will show right through. You can obtain the selection and unselected colors from the receiver, and remember to revert the colors if the isSelected argument is false.
If your receiver has keyboard focus and is editable, your renderer should paint itself in a distinctive fashion. The following example retrieves the focus properties from the static UIManager object; if not in focus, it applies an EmptyBorder (2 pixels at the sides, 1 pixel top and bottom) to the renderer. Note that, if the border widths don't line up exactly, this can cause the JLabel to shift by a small amount.
The only Swing component with scrolling behavior is JScrollPane. [?What about JComboBox?] Others that typically scroll (JTable, JTree, JList) must become a client of a JViewport embedded within a JScrollPane. Fortunately, there are JScrollPane convenience constructors that take one of these three components.
Many apps rely on a combination of which mouse button was pressed, whether it was (single, double, triple)-clicked, and whether any modifier keys (shift, control, alt, meta) were held on the keyboard at the same time.
The following example creates an anonymous [? really ?] subclass of java.awt.event.MouseAdapter (which can be declared as type java.awt.event.MouseListener because MouseAdapter implements that interface). It overrides/implements only one of the five methods, mouseClicked(). It can refer to list because the latter is declared final.
Or we could write it this way, passing an anonymous Adapter class to addMouseListener():
Or this way, with a named inner (or outer) class:
The com.sun.java.swing.BoxLayout layout manager organizes the contents of its clients in a single horizontal or vertical row, along with optional spacers. A series of boxed JPanels can do everything java.awt.GridLayout can (with better control), and can emulate a java.awt.GridBagLayout with much greater simplicity. The com.sun.java.swing.Box lightweight container is limited to using BoxLayout, and may be convenient if you don't want to use a Border on it.
The spacers created by the Box.createHorizontalGlue() and createVerticalGlue() are misnamed, IMHO. You think of glue as pulling objects together. Such an object acts more like a spring (but could be confused with the now-defunct SpringLayout), sponge, wadding or gas: it expands to fill the available space between other components, pressing them against the edges of the container.
The inner class Box.Filler is more constrained. Its constructor takes minimum, preferred and maximum sizes (java.awt.Dimension objects, typically based on the size of the components around it) and stretches to ensure at-least-this-much but not-more-than-this space is inserted.
PropertyResourceBundles (which are merely text files with the extension .properties) are capable of storing only strings. However, with the right parser, it's easy enough to translate those strings into other objects. The example below retrieves a string, a string that sets the text on a JButton, a string that's the URL for an Icon for the JButton, and the subclass for a JMenuItem. The string keys in the props file can be anything you want, but typically they're formatted as dot-delimited hierarchies. Space within a value is significant, but outside is not. You can continue onto subsequent lines with a backslash character. Comments are indicated by a hash (#) in the first column (as with shell scripts and Perl), and lines can be continued with a backslash.
## Props file guiMain.properties about.copyright =(c)2001 Underbase Corp. about.dept =Cybertron Third Age about.email =archivist@c3a.underbase.org dialog.button.txt=Revert dialog.button.ico=Icons/revert.gif dialog.button.tip=\ Press this button to return the database to its last saved state. menubar.edit.delete.class = JMenu menubar.edit.format.class = JCheckBoxMenuItem menubar.view.normal.class = JRadioButtonMenuItem menubar.view.outline.class= JRadioButtonMenuItem menubar.view.preview.class= JRadioButtonMenuItem
Load the bundle, then some properties from it. Note that the .properties extension is omitted from the getBundle() method.
An equivalent ListResourceBundle subclass is as follows. The only method that need be overridden is getContents, which should return an Object[][] array, with the first column being the String keys. Note that, unlike in a non-code PropertiesResourceBundle, a ListResourceBundle can actually instantiate and maintain references to objects, so some of the above properties are no longer necessary. On the flip side, you have to recompile this to make changes, whereas you can simply text-edit a PropertiesResourceBundle and restart an applet.