Java swing components can be extended in various ways. This blog shows how to implement a custom renderer for a JList that uses checkboxes in front of each list element. A “normal” JList will highlight selected elements by changing the background of the selected elements, but in the blog’S example the checkboxes renderer will use checkboxes to show the selection state.
Before we can start to implement a custom ListCellRenderer we must understand what renderers in swing are and how they are used by swing components to render their content.
Swing renderers
A lot of components in swing are used to display data structures that are made up of multiple elements, e.g. JList, JTable, JTree. Therefore these swing components must know how to arrange the elements and how to draw each element. For this purpose java swing introduced the renderers.
A renderer in swing is used to create a swing component that is responsible for drawing one element of a collection component like JList. A JList uses a renderer to draw each element that the list’s model contains.
For a JList these process can be described in this way:
- For each element in the ListModel
- Ask the ListCellRenderer to return a Component that can draw the element
- calculate the clipping area
- Use the render component returned by the ListCellRenderer to paint the clipping area for the element
A CheckboxListCellRenderer implementation
As explaint in the “Swing renderers” section above we can customize the way a JList element is rendered by implementing a ListCellRenderer. In this blog I want to show how one can render checkboxes in front of the list elements that represent the selection state.
The resulting example application will look like this:
The text area at the bottom is only a text representation of the JList’s selection state to show that the checkboxes really represent this state.
The renderer implementation
public class CheckboxListCellRenderer<E> extends JCheckBox implements ListCellRenderer<E> { private static final long serialVersionUID = 3734536442230283966L; @Override public Component getListCellRendererComponent(JList<? extends E> list, E value, int index, boolean isSelected, boolean cellHasFocus) { setComponentOrientation(list.getComponentOrientation()); setFont(list.getFont()); setText(String.valueOf(value)); setBackground(list.getBackground()); setForeground(list.getForeground()); setSelected(isSelected); setEnabled(list.isEnabled()); return this; } }
The ListCellRenderer’s getListCellRendererComponent method API says
Return a component that has been configured to display the specified value. That component’s
paint
method is then called to “render” the cell. If it is necessary to compute the dimensions of a list because the list cells do not have a fixed size, this method is called to generate a component on whichgetPreferredSize
can be invoked.
The interressting part of the implementation is line 20 where this is returned. So what does it mean? It means that we can implement a ListCellRenderer in that way that itself is a java component and that also means that the same instance is uesd again and again by the JList to draw it’s elements. There is no need to create a new component for each element, because the getListCellRendererComponent gives the renderer the chance to change it’s state according to the current element’s state that the JList wants to paint next.
Using a ListCellRenderer
Using a ListCellRenderer is very easy. You just have to set it.
JList<String> list = new JList<String>(); list.setCellRenderer(new CheckboxListCellRenderer<String>());
The complete source code of this blog is available at
https://github.com/link-intersystems/blog/tree/master/custom-ListCellRenderer.
Pingback: 我怎么用java swing复选框列出? – CodingBlog