Using Styles, Themes, and Painters with LWUIT Blog - lVcdfW

Version 2


    The L ightweight User Interface Toolkit (LWUIT) introduces a number of impressive functionalities to the Java ME UI developer. Styles, themes, and painters are three such functionalities that facilitate the development of highly attractive and device-independent visual elements. In this article, we see how to use them and explore some of the subtle issues.

    The demo applications have been developed on the Sprint Wireless Toolkit 3.3.1. Not only does this toolkit support LWUIT extremely well, it also has an interesting array of device emulators like those for HTC Touch and Samsung Instinct. If you intend to try out LWUIT, I would strongly suggest that you install the Sprint WTK on your computer.


    The concept of style is the foundation on whichtheming is built. The idea behind style is to centrally define the visual attributes for each component. In addition to its physical design, such as its shape, the appearance of a widget can be defined in terms of a number of common features:

    • Background and foreground colors: Each component has four color attributes: two each for background and foreground. A component is considered selected when it is ready for activation. When a button receives focus, for example, it is in the selected state and can be activated by being clicked. A component can have a background color for the selected state and another for the unselected one. Similarly, the foreground color (usually the color used for the text on the component) can be individually defined for the two states.

    • Text fonts: Text can be rendered using the standard font styles as supported by the platform, as well as bitmap fonts. The font for each component can be set through its style object.

    • Background transparency: The transparency of a component's background can be set to vary from fully opaque (the default setting) to fully transparent. The integer value 0 corresponds to full transparency and 255 to complete opacity.

    • Background image: By default, the background of a component does not have any image. However, this setting can be used to specify an image to be used as the background.

    • Margin and padding: The visual layout of a component (derived from the CSS Box Model) defines margin and padding. Figure 1 shows the meaning of the termsmargin and padding in the context of LWUIT. Note that the content area is used for displaying the basic content such as text or image. Style allows margin andpadding for each of the four directions (top, bottom, left, and right) to be individually set.

      Component layout
      Figure 1. Component layout

    • Background painters: Special-purpose painter objects can be used to customize the background of one or a group of components.

    The Style class represents the collection of all these attributes for each component that is used in an application and has appropriate accessor methods. In addition, this class also has the ability to inform a registered listener when the style object associated with a given component is altered.

    When a component is created, a default Style object gets associated with it. For any non-trivial application, the visual attributes will need to be modified. One way of doing this is to use the individual setter methods. If, for instance, the foreground color of a component (thiscomponent) has to be changed to red, the following code can be used:


    The second way to modify the settings of the default style is to create a new style and hook it up to the relevant component. TheStyle class has constructors that allow most of the attributes to be specified. The following code snippet sets a new style for a component:

    Font font = Font.createSystemFont (Font.FACE_SYSTEM,Font.STYLE_BOLD,Font.SIZE_LARGE); byte tr = (byte)255; Style newstyle = new Style (0x00ff00, 0x000000, 0xff0000, 0x4b338c, font, tr); thiscomponent.setStyle(newstyle); 

    This code sets new foreground and background colors, font for text, and background transparency. The constructor used here has the form:

    Style(int fgColor, int bgColor, int fgSelectionColor, int bgSelectionColor, Font f, byte transparency) 

    There is another form of this constructor that allows the image to be set, in addition to the above attributes. The attributes not supported by the constructor will, however, need to be set through the respective setter methods.

    Finally, visual attributes can also be set for an entire class of components (say, for all labels in an application) by using a theme, as we shall see a little later.

    Using Style

    We shall now build a simple display and see how style can be used to specify the appearance of a component. Our application will have a single form with a combo box and will look like the Figure 2:

    A simple ComboBox

    Figure 2. A simple combo box

    All the attributes of the combo box shown here have default values. The only exception is the foreground selection color, which had to be changed to improve the visibility of the selected item. Similarly, the form containing the combo box has just one modified attribute -- its background color. The following code shows how the form is created:

    . . . //create a form and set its title Form f = new Form("Simple ComboBox"); //set layout manager for the form //f.setLayout(new FlowLayout()); //set form background colour f.getStyle().setBgColor(0xd5fff9); . . . 

    The first two lines of code are quite self-explanatory and should be familiar to AWT/Swing developers. The third line sets the background color attribute for the form.

    The combo box is also instantiated in a similar manner:

    // Create a set of items String[] items = { "Red", "Blue", "Green", "Yellow" }; //create a combobox with String[] items ComboBox combobox = new ComboBox(items); 

    ComboBox is a subclass of List and needs a supporting data structure. Here we use a string array to represent this data structure.

    Once we have our combo box ready, we would like to change its foreground selection color to improve readability. So we write a line of code just as we had done for the form:


    However, when we compile the code and run it, the result turns out to be rather surprising -- the foreground color remains unchanged! It works for the form, so why doesn't it work for a combo box? To answer that question we need to keep in mind the basic architecture of LWUIT. Like Swing, LWUIT is designed around the MVC concept. So the entity that renders a component is logically separate from the component itself. Also, the rendering object for a combo box (among others) needs to be a subclass of Component, which means it will have its own Style. Every combo box is created with its default renderer, which is an instance ofDefaultListCellRenderer. When a combo box is drawn, the style used is that belonging to the renderer and that is why setting the foreground selection color in the Styleobject for the combo box does not work. To make the setting effective we have to modify the Style object for the renderer:

    //set foreground selection colour for //the default combobox renderer //this will work DefaultListCellRenderer dlcr = (DefaultListCellRenderer)combobox.getRenderer(); dlcr.getStyle().setFgSelectionColor(0x0000ff); 

    This time, when the code is compiled, it works.


    In the preceding section, we saw how to set individual visual attributes for a component. In an application with a large number of UI components, setting attributes for each component can be a tedious task and can also lead to errors. A Themeallows us to set, in a single place, the attributes for an entire class of components. This not only simplifies the task of setting attributes for all components of a particular type, but also ensures that any newly added component will look just like all the others of the same type in the application. A Themethereby establishes a visual coherence through all the screens of an application.

    A Theme is a list of key-value pairs with an attribute being a key and its value being the corresponding value. An entry in the list might look like this:

    Form.bgColor= 555555 

    This entry specifies that the background color of all forms in the application will be (hex) 555555 in the RGB format. A theme is packaged into a resource file that can also hold other items like images and bitmaps for fonts. The LWUIT download bundle includes a resource editor that offers a simple way to create a theme and package it into a resource file. The editor is available in the util directory of the bundle. Launch it by double-clicking on the icon, and the editor will open as shown below. The Resource Editor is also integrated into the Sprint WTK 3.3.1 and can be accessed by selecting File -> Utilities -> LWUIT Resource Editor, as seen in Figure 3.

    The Resource Editor

    Figure 3. The Resource Editor

    To create a new theme, click the + button on the left pane and a dialog for entering the name of the theme will open. This is shown in Figure 4.

    Creating a new theme

    Figure 4. Creating a new theme

    When you click OK, the name of the new theme appears on the left pane. Click this theme label to get a blank theme on the right pane, as seen in Figure 5.

    The blank theme

    Figure 5. The blank theme

    To populate the blank theme, click the Add button and the Add dialog will open. You can select a component and an attribute from the top combo boxes on this dialog. In Figure 6, the component selected is a form and the attribute selected is background color. The RGB value of the color can entered as a hex string in the space provided. You can also click on the colored box next to the space to entering the color value. This will open a color chooser, from which the value of the selected color will be directly entered into the dialog.

    Adding an entry to the theme

    Figure 6. Adding an entry to the theme

    Click the OK button and the entry will appear on the right panel of the main editor window. Note that entries can be edited or removed by using the appropriate button. Once all entries have been made, you can save it by selecting File -> Save As. If you are using the Sprint WTK, then the resource file for an application has to be in its res folder.

    Now that we have seen how to create a theme, let us look at a demo that illustrates its use. Our demo for this section also will have combo boxes but will look a little more polished than the one we have already seen. Figure 7 shows this demo screen. Note that now the form has a background image and the combo boxes are built around check boxes. Also, the title bar (at the top of the form) and the menu bar (at the bottom) have background colors different from the default (white).

    Demo screen with two combo boxes

    Figure 7. Demo screen with two combo boxes

    Before looking at the theme that is responsible for this difference in appearance, let us quickly check out the code used to make the screen.

    //initialise the LWUIT Display //and register this MIDlet Display.init(this); try { //open the resource file //get and set the theme Resources r ="/SDTheme1.res"); UIManager.getInstance(). setThemeProps(r.getTheme("SDTheme1")); } catch ( e) { //if there is a problem print a message on console //in this case default settings will be used System.out.println ("Unable to get Theme " + e.getMessage()); } //create a form and set its title Form f = new Form("ComboBox Example"); //set layout manager for the form f.setLayout(new FlowLayout()); //create two sets of items String[] items = { "Red", "Blue", "Green", "Yellow" }; String[] items2 = {"Sky", "Field", "Ocean", "Hill", "Meadow"}; //create two comboboxes with these items ComboBox comboBox = new ComboBox(items); ComboBox comboBox2 = new ComboBox(items2); 
    //create new instances of CbPainter //and set them to combo boxes //so that a checkbox will be //the basic building block CbPainter cbp = new CbPainter(); comboBox.setListCellRenderer(cbp); CbPainter cbp2 = new CbPainter(); comboBox2.setListCellRenderer(cbp2); //add the two combo boxes to the form f.addComponent(comboBox); f.addComponent(comboBox2); //create an "Exit" command and add it to the form f.addCommand(new Command("Exit")); //set this form as the listener for the command f.setCommandListener(this); //show this form; 

    Right at the beginning we see how to extract the theme from a resource file. The theme is then set for the UIManagerinstance. Here we have installed the theme at the start. But when a theme is set on the fly, some of the components of the form on screen may not be visible and the effect of setting a theme on these components is not predictable. To make sure that even the components that are not visible have their styles properly updated, you should call the refreshTheme method:


    The form and the combo boxes are created just as in our example in the preceding section. There is no code that adds visual gloss to this demo, as all attributes are specified in a Theme. What is different here is that instead of letting the combo boxes be drawn by the default renderer, we have set our own renderers. This is shown by the highlighted part of the code. These custom renderers make the combo boxes look different.

    The renderer itself is very simple. All it has to do is implement the methods specified in the interfaceListCellRenderer. As we want our combo box to encapsulate a checkbox, the renderer extends CheckBox. ThedrawComboBox method of theDefaultLookAndFeel class uses this renderer to get the component to be used for drawing the combo box. In this case the component so obtained is a checkbox, as we see from the code below.

    //objects of this class will be used to paint the combo boxes class CbPainter extends CheckBox implements ListCellRenderer { public CbPainter() { super(""); } //returns a properly initialised component //that is ready to draw the checkbox public Component getListCellRendererComponent (List list,Object value,int index,boolean isSelected) { setText("" + value); if (isSelected) { setFocus(true); setSelected(true); } else { setFocus(false); setSelected(false); } return this; } //returns the component required for drawing //the focussed item public Component getListFocusComponent(List list) { setText(""); setFocus(true); setSelected(true); return this; } } 

    It is not necessary that a combo box should look only like a plain list or a checkbox. It can be built around some other standard component or even around a totally new component with its own unique look. Figure 8 shows a combo box that has a radio button as its renderer.

    ComboBox with a radio button renderer

    Figure 8. ComboBox with a radio button renderer

    To see the theme that defines the look of our demo, you will need the Resource Editor on your computer. Launch either the Resource Editor that comes with the LWUIT download or the one integrated into the Sprint Toolkit. Once the Resource Editor opens, select File -> Open to locate and open the resource file. The Resource Editor will showSDTheme1 on the left panel under Themes. ClickingSDTheme1 will display the details of the theme on the right panel as shown in Figure 9.

    The theme for the demo

    Figure 9. The theme for the demo

    The first point to note is that there is one entry at the bottom that appears in bold letters. All such entries are the defaults. In our example, the only component-specific font setting is for the soft button -- the Exit button at left bottom corner. The fonts for the form title and the combo box string are not defined. These fonts will be rendered as per the default setting.

    In our earlier example, we saw that the selection color for the text had to be set in the renderer. In the present example, we know the rendering is actually being done by a checkbox renderer. So the background and foreground colors have been defined for checkboxes and, indeed, the colors for rendering the text and the text background (both for the focussed and non-focussed states) are as per these definitions. This can be seen in Figure 10.

    Foreground and background colours

    Figure 10. Foreground and background colors

    In the figure above we can also see the effect of checkbox transparency value of 127 (semi-transparent). The three unselected entries in the drop-down list have a dark tint because of this transparency setting. You can experiment with this value to see how these backgrounds change. Incidentally, when you make a change in the theme, it is not necessary to rebuild the application. Just save the resource file and click Run.

    When a new theme is installed, all applicable styles are updated except those attributes that have been manually altered by using one of the accessor methods of the Style class discussed earlier. However, if you want the new theme to be effective even for the attributes that have been manually changed, then use one of the setters in Stylethat take two arguments, the second one being a Boolean variable. For example:

    setFgColor(int fgColor, boolean override); 

    If the Boolean argument is set to true when an attribute is manually changed, then the values specified in the new theme will override the manually set value too. The code will look like this:

    thiscomponent.getStyle().setFgColor(0xff0000, true); 


    The Painter interface allows the background of a component to look the way you want. Recall our discussion on style where we had seen that one of the attributes was background painter. In this section we shall see how a simple background painter can be used.

    Referring to our demo screenshot, the color of the background on which the text has been drawn cannot be changed through style or theme. The reason for this becomes clear when we analyze the structure of a combo box, as shown in Figure 11, and the sequence of rendering it.

    Structure of our combo box

    Figure 11. Structure of our combo box

    When a combo box needs to be redrawn (say, because it has just received focus), the following sequence of events takes place.

    1. The obsolete combo box is deleted. This is done by drawing a filled rectangle of the same size and with a transparency of 0 (fully transparent).
    2. Then the checkbox selection and the text are drawn.
    3. Next the combo button is drawn.
    4. And finally, the combo border is drawn.

    We see now that the combo background is not redrawn after the first step. So this part remains a fully transparent layer and it is the form background that shows through. You can change the form background color in the theme and you will see that this color also becomes the combo background color.

    If we now want to have a different color (or a pattern or an image) on the combo background, we need to use aPainter. We shall see what a simple painter looks like and how to use it.

    public class ComboBgPainter implements Painter { private int bgcolor; public ComboBgPainter(int bgcolor) { this.bgcolor = bgcolor; } public void paint(Graphics g, Rectangle rect) { //probably redundant //but save the current colour anyway int color = g.getColor(); //set the given colour g.setColor(bgcolor); //get the position and dimension //of rectangle to be drawn int x = rect.getX(); int y = rect.getY(); int wd = rect.getSize().getWidth(); int ht = rect.getSize().getHeight(); //draw the filled rectangle g.fillRect(x, y, wd, ht); //restore colour setting g.setColor(color); } } 

    The code is simple enough -- all it does is draw a filled rectangle using the color passed to the constructor. The rectangle is drawn at the position and with the dimensions defined byrect.

    What we now have to do is hook up the painter to the combo box that needs to have its background painted. We do it by adding the highlighted line after the code instantiating the two combo boxes. Note that only one combo box will have its background painted.

    //create two comboboxes with these items ComboBox combobox = new ComboBox(items); ComboBox combobox2 = new ComboBox(items2); 
    //set the painter combobox.getStyle().setBgPainter (new ComboBgPainter(0x4b338c)); 

    Figure 12 shows that the background of the combo box on the left has been painted as expected. If we had wanted to paint the background of the other combo box too, we would have used the same painter. As a matter of fact, we could create an instance of the painter and set the same instance on all combo boxes.

    Combo box with painted background

    Figure 12. Combo box with painted background


    We have seen how we can use Style,Theme, and Painter to create a set of visually attractive and uniform components with the LWUIT platform. Recently LWUIT has been open sourced. A detailed study of the source code is a very fascinating experience and will develop the kind of insight required for proper utilization of this library and also for interesting experimentation.