O'Reilly logo

Swing Hacks by Chris Adamson, Joshua Marinacci

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

92
|
Chapter 2, Lists and Combos
#19 Turn Methods into List Renderers
HACK
setting a flag so that the cell renderer applies only the colorized foreground
and background colors to that cell.
H A C K
#19
Turn Methods into List Renderers Hack #19
By using a little bit of reflection, you can make a generic ListCellRenderer
that can render data using any method at runtime.
JLists, like JTable and JTree, use a decorator pattern to customize how they
look. This system of cell renderers works well, but it can require you to
build a unique renderer class for each type of object you want to put into
your lists. Often, all you really want to do is call a particular method on the
objects in your list, but writing a complete class to just call one method is a
lot of work for such a small task. This hack shows you how to use reflection
to create a generic cell renderer that can be reused on any object without
subclassing.
Building a Generic Renderer
The default JList cell renderer will just call toString( ) on the objects in the
list and draw the resulting string to the screen. This is fine for simple uses
where you really are just looking at a list of strings or objects with appropri-
ate
toString( ) methods. More complicated applications—and they all
become more complicated eventually—require more complicated objects,
and those objects might not have a convenient or useful
toString( ) method.
Eventually, you have to write a custom renderer for the particular object you
wish to store. But there is another way: reflection.
Reflection lets you programmatically discover and access methods and fields
in a java class at runtime. For this hack, you will use reflection to call an
arbitrary method. This will allow the programmer using your generic ren-
derer to specify a method using a string. This method will be used to render
the component. Because you will be using reflection, you don’t need to
Figure 2-11. Fading in a cell selection
Turn Methods into List Renderers #19
Chapter 2, Lists and Combos
|
93
HACK
know the kind of objects in the list. As long as a method with the requested
name exists, you can call it and get a value out. This will work even if some
of the objects in the
JList
have different types. But let’s not get ahead of
ourselves. First, you need a basic cell renderer, as seen in Example 2-21.
Example 2-21 declares a subclass of the
DefaultListCellRenderer—the stan-
dard implementation of a
ListCellRenderer. The GenericListCellRenderer
class takes a method string in its constructor. This string is the name of the
method to call on the list value objects.
All
ListCellRenderers have a getListCellRendererComponent( ) method,
which returns a component to do the actual drawing. Most implementa-
tions (
DefaultListCellRenderer included) use JLabels as the drawing com-
ponents because they are relatively lightweight and can have both text and
icons. The previous code gets the
JLabel component from the superclass and
sets the text to my text. Once added to a
JList, this code will be called for
each item in the list, meaning they will all be drawn as my text. This works,
but it isn’t very useful. Now it’s time to add some reflection:
try {
Method meth = value.getClass( ).getMethod(method,null);
if(meth != null) {
Object retval = meth.invoke(value,null);
label.setText(""+retval);
}
} catch (Exception ex) {
System.out.println("got an execption: " + ex);
ex.printStackTrace( );
label.setText(""+value);
}
return label;
Example 2-21. A basic cell renderer
public class GenericListCellRenderer extends DefaultListCellRenderer {
protected String method;
public GenericListCellRenderer(String method) {
super( );
this.method = method;
}
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel)super.getListCellRendererComponent(
list,value,index, isSelected, cellHasFocus);
label.setText("my text");
return label;
}

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required