Java Programming, Lecture Notes # 211, Revised 03/24/99.
Students in Prof. Baldwin's Advanced Java Programming classes at ACC will be responsible for knowing and understanding all of the material in this lesson beginning with the spring semester of 1999.
This lesson was originally written on October 3, 1998, using the JDK 1.1.6 download package along with Swing 1.0.3. The purpose of this lesson is to illustrate the use of MVC models with Swing components.
The sample program was upgraded to JDK 1.2 on 3/24/99 by modifying the import directives to make them compatible with the version of Swing contained in JDK 1.2.
The material in this lesson assumes that you have studied my earlier lesson on Understanding Component MVC Models. The sample program in this lesson is a modification of the sample program in that lesson. In this lesson, I will discuss only the new material in the program. To understand the entire program, you may need to refer to the discussion of the original program. It will also be helpful if you have studied my earlier lesson on using the JList class to create simple lists.
Swing gives you the ability to control how widgets look, how they respond to input, and in some cases, how their data is represented. The lesson mentioned above discussed the third capability involving data representation in detail.
The primary topic of this lesson is the first capability in the list: controlling how widgets look. I will show you how you can control the appearance of the elements in a JList object from two different aspects. The first aspect has to do with the use of Pluggable Look and Feel (PLAF). I have discussed this topic in several previous lessons that you may need to go back and review. You will need to go back to the lesson entitled Swing, Hidden Buttons with Icons, Icon Images, Borders, Tool Tips, Nested Buttons, and Other Fun Stuff and extract the code from that lesson for the class named PlafPanel02.java. You will need that code in this lesson.
PLAF really isn't new to this lesson. I included it in this lesson simply for completeness. The second aspect, and the new information in this lesson is how to create and use a custom cell rendering class to cause the cells in the JList object to be rendered according to your specifications.
I will use an object of the JList class as the vehicle for this discussion, although the general concepts discussed here apply to several of the more complex Swing components including:
If you don't provide a custom cell rendering class, the cells in a JList object are rendered as black text on a white or colored background. Depending on the look and feel implementation being used, selecting an element in the list causes its color or the color of its background to change in an obvious way. The sample program in this lesson creates two different JList objects for comparison. One uses default rendering and the other uses a custom cell renderer.
There are basically two steps involved in creating and using a custom cell renderer. First you must define a class that implements the ListCellRenderer interface. This interface declares one method as described below:
public java.awt.Component getListCellRendererComponent(JList list, Parameters: |
This method returns a Component object designed to display the specified value in the appropriate manner. That component's paint method is then called to "render" the cell. As is usual, you can use any of the incoming parameters to accomplish your goal. The sample program in this lesson uses the two parameters, value and isSelected, to display the cell's text and an icon, which toggles between two different images depending on whether or not the cell is selected.
The second step is to invoke the following method on the JList object passing an object of your new cell renderer class as a parameter.
public void setCellRenderer(ListCellRenderer cellRenderer) Sets the delegate that's used to paint each cell in the list. If prototypeCellValue was set then the fixedCellWidth and fixedCellHeight properties are set as well. Only one PropertyChangeEvent is generated however for the "cellRenderer" property. The default value of this property is provided by the ListUI delegate, i.e. by the look and feel implementation. This is a JavaBeans bound property. Parameters: |
Once you have done these two things, the cells in your list will be rendered using your new cell renderer object.
The name of this program is SwingList03.java. The purpose is to illustrate custom cell rendering for a Swing JList component.
It also illustrates the use of the ListSelectionListener interface to instantiate listener objects that monitor for the selection of an element in the list, retrieve the index value of the element, and display the value.
It also illustrates the ability to remove an element from a JList object.
This program populates two JList objects with identical data for comparison purposes. The data used to populate the two lists is obtained from the names of the files and directories in the root directory of the C-drive.
The two lists are identical except for their appearance. One of the lists renders each element simply as text. For this list, the background color for an element changes to a different color when the element is selected.
The other list renders each list element as an icon and some text. When an element is selected, the icon is a small red ball. When an element is not selected, the icon is a small blue ball. You will need to furnish your own images for the icons, so your images will probably be different.
Both lists use the DefaultListModel that has the ability to remove an element from the list. Both will throw an exception if you attempt to remove an element from an empty list. They will also throw an exception if you attempt to remove an element with an invalid index in the associated text field.
The data to populate the two lists is automatically obtained from the root directory on the C-drive. When the program starts, the two populated lists, two buttons, and two text fields appear on the screen. The buttons and text fields should appear to the right of the list with which they are associated.
To remove an element from a list, enter the index in the associated text field and click the associated button.
To determine the index value of an element, simply select it with the mouse or an arrow key. The index number will be placed in the text field. Clicking the associated button at that point will cause the selected element to be removed from the list. You can also manually enter an index value into the text field causing an element other than the selected element to be removed.
A PLAF control panel is also displayed on the screen. You can change the look and feel by clicking a button on the control panel.
The program was tested using JDK 1.1.6 and Swing 1.0.3 under Win95. A revised version also tested using JDK 1.2.
This is a modification of the program named SwingList02 from a previous lesson. Most of the code is identical to, or very similar to the code in that program. In this lesson, I will discuss only the code that is new or significantly different from the earlier program. You can view all of the code in the listing of the program that follows later.
The first fragment shows the beginning of the constructor and the statement to instantiate a PLAF control panel and link it to this application. As mentioned earlier, you will need to extract the code for PlafPanel02 from an earlier lesson.
public SwingList03 () {//constructor new PlafPanel02(this); |
The next fragment shows the instantiation of the two JList objects using the DefaultListModel as their data model.
More importantly, this fragment invokes the setCellRenderer() method on the first list to cause the custom cell renderer to be used whenever it is necessary to redraw a cell in that list.
listA = new JList(new DefaultListModel()); listA.setCellRenderer(new CustomCellRenderer()); listB = new JList(new DefaultListModel()); |
Now I am going to skip all the way down to the definition of the class used to instantiate the custom cell renderer object. Note that this class implements the ListCellRenderer interface that declares only one method named getListCellRendererComponent.
Once an object of this class is defined as the cell renderer for a list (as in the previous fragment) this method is invoked whenever the system needs to render a cell in that list. The method returns a Component object whose paint() method is used to render the cell.
With this definition of the method, the cell is rendered using a JLabel, because this class extends JLabel and returns this. The code in the method causes the text in the JLabel to be the toString() representation of the value received as a parameter, and causes the icon to be one of two choices depending on the state of the incoming parameter named isSelected. Once you know the purpose of the method, the actual code in this method should be pretty familiar to you so I won't discuss it further.
class CustomCellRenderer extends JLabel implements ListCellRenderer{ ImageIcon selected = new ImageIcon("red-ball.gif"); ImageIcon unSelected = new ImageIcon("blue-ball.gif"); public Component getListCellRendererComponent( JList list, // the list being redrawn Object value, // value to display int index, // cell index boolean isSelected, // is the cell selected boolean cellHasFocus)// the list and the cell have // the focus {//begin getListCellRendererComponent() body String theLabel = value.toString(); setText(theLabel); if(isSelected){//set the red ball setIcon(selected); }else{//set the blue ball for not selected setIcon(unSelected); }//end else return this;//return component used to render }//end getListCellRendererComponent() }//end class CustomCellRenderer |
As mentioned earlier, you will need to provide your own images. Just substitute the names of your image files in place of those in the fragment to use your images in place of mine.
The code in the program that was not highlighted in the fragments above can be viewed in the complete listing of the program that follows in the next section.
A complete program listing is provided in this section.
/*File SwingList03.java Rev 03/24/99 Upgraded to JDK 1.2 on 3/24/99 This is a modification of the program named SwingList02. The purpose of this program is to illustrate custom cell rendering for a Swing JList component. It also illustrates the use of the ListSelectionListener interface to instantiate listener objects that monitor for the selection of an element in the list, retrieve the index value of the element, and display the value. This program should be discussed only after the student understands how to create and use JList objects as described in SwingList01.java. This program populates two JList objects with identical data. The data used to populate the two lists is obtained from the names of the files and directories in the root directory of the C-drive. Both of the JList objects are based on the DefaultListModel. The two lists are identical except for their appearance. One of the lists renders each element simply as text. For this list, the background for an element changes to a different color when the element is selected. The other list renders each list element as an icon and some text. When an element is selected, the icon is a small red ball. When an element is not selected, the icon is a small blue ball. You will need to furnish your own images for the icons, so your images will probably be different. Both lists use the DefaultListModel which has the ability to remove an element from the list. (Both will throw an exception if you attempt to remove an element from an empty list.) The data to populate the two lists is automatically obtained from the root directory on the C-drive. When the program starts, the two populated lists, two buttons, and two text fields appear on the screen. The buttons and text fields should appear to the right of the list with which they are associated. To remove an element from a list, enter the index in the associated text field and click the associated button. To determine the index value of an element, simply select it with the mouse or an arrow key. The index number will be placed in the text field. Clicking the associated button at that point will cause the selected element to be removed from the list. You can also manually enter an index value into the text field causing an element other than the selected element to be removed. (The program runs under JDK 1.1.6 whether compiled using the JDK or the Microsoft jvc. However, it won't run under my current version of Microsoft jview even when compiled using jvc. It throws an exception in the area of populating the Vector object.) Tested using JDK 1.1.6 and Swing 1.0.3 under Win95. Also tested using JDK 1.2 and Win95. **********************************************************/ import java.io.*; import java.util.*; import java.awt.*; import java.awt.event.*; //import com.sun.java.swing.*; //JDK1.1/Swing1.0.3 version |
-end-