Create a cooler jlist Interface
Content:
1. How the painter works.
2. Use a custom Paster to change the jlist and jcombobox appearances.
3. Let the new appearance respond to the mouse event.
With the MVC design concept of the Swing System, it is easy to replace different appearances of components. This document uses jlist and jcombobox as examples to explain the principle and usage of listcellrenderer.
I. How the painter works
Both jlist and jcombobox use listcellrenderer, because jcombobox itself is composed of a drop-down jlist and textfield. Here, they use the callback mechanism.
One of the common callback methods is to call methods in Class B in Class A. In Class A, you must first register one (or multiple) Class B instance references, call the internal method of the instance when you need to call it. this mechanism is useful in many design patterns, such as observer. callback is also used for the AWT event mechanism.
To implement callback, Class B is usually designed as an interface that can be callback. In the jlist painter, swing provides a listcellrenderer interface,
Public interface listcellrenderer {
Component getlistcellrenderercomponent (
Jlist list,
Object value,
Int index,
Boolean isselected,
Boolean cellhasfocus );
}
This interface provides only one method. If we implement this interface and pass its instance reference to jlist, we can replace jlist with different styles. let's take a look at how listcellrenderer works,
Before drawing every cell in the jlist, it will call getlistcellcomponent () to obtain a component and
Draw this component in the correct position. Because getlistcellcomponent () returns component, we can extend almost any component to change the appearance of jlist, jcombobox, and so on.
2. Make your own Paster
Now we want to display a group of students in the jlist and the student icon in front of each list, as shown in.
Let's first think about what components in swing can both display icons and text? Jlabel. Let's use jlabel as the jlist painter. Let's take a look at my extended jlabel class, which implements the listcellrenderer interface:
/* Listcell painter that can display icons */
Public class iconlistitemrenderer extends jlabel implements listcellrenderer
{
Private border
Selectedborder = borderfactory. createlineborder (color. Blue, 1 ),
Emptyborder = borderfactory. createemptyborder (1, 1, 1 );
Public component getlistcellrenderercomponent (
Jlist list,
Object value,
Int index,
Boolean isselected,
Boolean cellhasfocus)
{
Iconlistitem item = (iconlistitem) value;
This. seticon (item. getIcon ());
This. settext (item. gettext ());
If (isselected) setborder (selectedborder );
Else setborder (emptyborder );
Return this;
}
}
As you can see, the getlistcellrenderercomponent method will pass in several parameters, and we will use these parameters to set the jlabel appearance: icons and text. In this class, we use an iconlistitem to receive the value passed by the caller,
Iconlistitem item = (iconlistitem) value;
Iconlistitem is another defined class that stores the values of each list item,
Import javax. Swing .*;
Public class iconlistitem
{
Icon;
String text;
Public iconlistitem (icon, string text)
{
This. Icon = icon;
This. Text = text;
}
Public icon getIcon () {return icon ;}
Public String gettext () {return text ;}
Public void seticon (icon) {This. Icon = icon ;}
Public void settext (string text) {This. Text = text ;}
}
In this way, we can use the getIcon () and gettext () methods to obtain the value of each list item,
Iconlistitem item = (iconlistitem) value;
This. seticon (item. getIcon ());
This. settext (item. gettext ());
Now, we can use the following methods to conveniently change the jlist appearance,
Jlist list = new jlist ();
List. setcellrenderer (New iconlistitemrenderer (); file: // install our custom cellrenderer
Defaultlistmodel listmodel = new defaultlistmodel ();
List. setmodel (listmodel );
Iconlistitem item = new iconlistitem (New imageicon (...), "John ");
Listmodel. addelement (item); // Add an item to the list
...
Jcombobox also has a drop-down list, so its list is also drawn using listcellrenderer, so we can also give this iconlistitemrenderer to it:
Jcombobox list = new jcombobox ();
List. setrenderer (New iconlistitemrenderer (); // installs our custom cellrenderer
Defaultcomboboxmodel combomodel = new defaultcomboboxmodel ();
List. setmodel (combomodel );
Iconlistitem item = new iconlistitem (New imageicon (...), "John ");
Combomodel. addelement (item); // Add an item to the list
...
Note that the setrenderer () method is used when jcombobox is installed, and the jlist method is setcellrenderer (). The name is slightly different.
What we can see above is a list that can display an icon. Next we will look at how a list that can display the checkbox is implemented. The following is an example:
Code implementation:
Import javax. Swing .*;
Import java. AWT .*;
Import javax. Swing. Border .*;
Import java. AWT. event .*;
/* Display the listcell painter of the checkbox */
Public class checklistitemrenderer extends jcheckbox implements listcellrenderer
{
Public component getlistcellrenderercomponent (
Jlist list,
Object value,
Int index,
Boolean isselected,
Boolean cellhasfocus)
{
Checklistitem item = (checklistitem) value;
This. setselected (item. getcheck ());
This. settext (item. gettext ());
This. setfont (list. getfont ());
This. setenabled (list. isenabled ());
Return this;
}
}
In the same way, a checklistitem is used to store the values of each list item in the painter:
Public class checklistitem
{
Boolean check;
String text;
Public checklistitem (Boolean check, string text)
{
This. Check = check;
This. Text = text;
}
Public Boolean getcheck () {return check ;}
Public void setcheck (Boolean _ Check) {check = _ check ;}
Public String gettext () {return text ;}
Public void settext (string _ text) {text = _ text ;}
}
The usage of this Paster is the same as that of iconlistitemrenderer.
3. Let the custom Paster ring the mouse event
When the above checklistitemrenderer is used, you will find that although the checkbox can be displayed in the list, it does not respond when you click with the mouse! Now I will solve this problem. It should be clarified that listcellrenderer itself only returns one component to draw a cell and cannot respond to user actions. For some, we must work on jlist. jlist has an addmouselistener () method to install a mouse listener for itself. Here, I implemented a mouseadapter and asked it to respond to mousepressed:
Class checklistmouselistener extends mouseadapter
{
Public void mousepressed (mouseevent e ){
Jlist list = (jlist) E. getsource ();
Int Index = List. locationtoindex (E. getpoint ());
Checklistitem item = (checklistitem) List. GetModel (). getelementat (INDEX );
Item. setcheck (! Item. getcheck ());
Rectangle rect = List. getcellbounds (index, index );
List. repaint (rect );
}
}
Use addmouselistener (New checklistmouselistener.
In addition to the jlist containing the checkbox, in many cases, we need to add action responses to the self-made Paster. For example, to implement an editable jlist, in addition to extending jtextfield and implementing listcellrenderer, you also need to write a mouse listener and a keyboard listener. When you double-click the listener, jlist becomes editable. When you press enter, jlist becomes uneditable.