Java SE 6 Update 10 release and newer contain Nimbus, a cross-platform Look and Feel implemented with Synth. However, for backwards compatibility, Metal is still the default Swing look and feel.[3]
However synth does not provide a default look, and components that are not defined in the synth XML file will not be painted. It is however possible to assign a default style to all other widgets, and customize styles for some specific widgets only.
The following XML declaration defines a style named textfield and binds it to all text fields. The defaultStyle allows to set a default font, foreground and background colors to all other widgets.
Supposing that the XML declaration is defined in a file named synthExample.xml, the following code loads the XML definition file and sets the current look and feel to synth (loading a synth Look and Feel is done using the load method of the SynthLookAndFeel class):
Creating a custom look and feel, or modifying an existing one, can be a daunting task. The javax.swing.plaf.synth package can be used to create a custom look and feel with much less effort. You can create a Synth look and feel either programmatically or through the use of an external XML file. The discussion below is devoted to the creation of a Synth look and feel using an external XML file. Creating a Synth c programmatically is discussed in the API documentation.
SynthStyle provides style information used by the Synth ComponentUI implementation. For example, SynthStyle defines the foreground and background color, font information, and so forth. In addition, each SynthStyle has a SynthPainter that is used to paint the region. For example, SynthPainter defines the two methods paintScrollBarThumbBackground and paintScrollBarThumbBorder, which are used to paint the scroll bar thumb regions.
The programmatic route involves creating an implementation of SynthStyleFactory that returns SynthStyles. The following code creates a custom SynthStyleFactory that returns distinct SynthStyles for buttons and trees:
The element is the basic building block of the Synth XML file. It contains all the information needed to describe a region's rendering. A element can describe more than one region, as is done here. In general, though, it is best to create a element for each component or region. Note that the element is given an identifier, the string "basicStyle." This identifier will be used later in the element.
The element of the element will be discussed below. The element of a region can have one, or a mixture, of seven possible values. When the value is not specified, the definition applies to all states, which is the intention here. Therefore, the background and foreground colors "for all states" are defined in this element.
Finally, the element with the identifier "basicStyle" that has just been defined is bound to all regions. The element binds "basicStyle" to "region" types. Which region type or types the binding applies to is given by the "key" attribute, which is ".*" in this case, the regular expression for "all."
type is either "name" or "region." If type is a name, obtain the name with the component.getName() method. If type is a region, use the appropriate constant defined in the Region class in the javax.swing.plaf.synth package.
When you bind a style to a region, that style will apply to all of the components with that region. You can bind a style to more than one region, and you can bind more than one style to a region. For example,
You can bind to individual, named components, whether or not they are also bound as regions. For example, suppose you want to have the "OK" and "Cancel" buttons in your GUI treated differently than all the other buttons. First, you would give the OK and Cancel buttons names, using the component.setName() method. Then, you would define three styles: one for buttons in general (region = "Button"), one for the OK button (name = "OK"), and one for the Cancel button (name = "Cancel"). Finally, you would bind these styles like this:
Just as a style can be bound to multiple regions or names, multiple styles can be bound to a region or name. These multiple styles are merged for the region or name. Precedence is given to styles defined later in the file.
The element allows you to define a look for a region that depends on its "state." For example, you will usually want a button that has been PRESSED to look different than the button in its ENABLED state. There are seven possible values for that are defined in the Synth XML DTD. They are:
The value that is used is the defined state that most closely matches the state of the region. Matching is determined by the number of values that match the state of the region. If none of the state values match, then the state with no value is used. If there are matches, the state with the most individual matches will be chosen. For example, the following code defines three states:
If the state of the region contains at least SELECTED and PRESSED, state one will be chosen. If the state contains SELECTED, but not does not contain PRESSED, state two will be used. If the state contains neither SELECTED nor PRESSED, state zero will be used.
When the current state matches the same number of values for two state definitions, the one that is used is the first one defined in the style. For example, the MOUSE_OVER state is always true of a PRESSED button (you can't press a button unless the mouse is over it). So, if the MOUSE_OVER state is declared first, it will always be chosen over PRESSED, and any painting defined for PRESSED will not be done.
The code above will work properly. However, if you reverse the order of the MOUSE_OVER and PRESSED states in the file, the PRESSED state will never be used. This is because any state that is PRESSED state is also a MOUSE_OVER state. Since the MOUSE_OVER state was defined first, it is the one that will be used.
Each of the element and the element has an alternate usage. Each can have an id attribute or an idref attribute. Using the id attribute, you can define a color that you can reuse later by using the idref attribute. For example,
The insets add to the size of a component as it is drawn. For example, without insets, a button with a caption of Cancel will be just large enough to contain the caption in the chosen font. With an element like this
Synth's file format allows customizing the painting by way of images. Synth's image painter breaks an image into nine distinct areas: top, top right, right, bottom right, bottom, bottom left, left, top left, and center. Each of the these areas is painted into the destination. The top, left, bottom, and right edges are tiled or stretched, while the corner portions (sourceInsets) remain fixed.
There is no relation between the element and the sourceInsets attribute. The element defines the space taken up by a region, while the sourceInsets attributes define how to paint an image. The and sourceInsets will often be similar, but they need not be.
The lines inside the element specify that the background of buttons should be painted using the image images/button.png. That path is relative to the Class that is passed into SynthLookAndFeel's load method. The sourceInsets attribute specifies the areas of the image that are not to be stretched. In this case the top, left, bottom, and right insets are each 10. This will cause the painter not to stretch a 10 x 10 pixel area at each corner of the image.
Here is an example, using the button style defined above. The button style, plus a "backing style" with definitions of font and colors that are bound to all regions (similar to the "basicStyle" shown in the section titled "The XML File," above) are combined in buttonSkin.xmlHere is a listing of buttonSkin.xml:
We can load this XML file to use the Synth look and feel for a simple application called SynthApplication.java. The GUI for this application includes a button and a label. Every time the button is clicked, the label increments.
Radio buttons and check boxes typically render their state by fixed-size icons. For these, you can create an icon and bind it to the appropriate property (refer to the properties table, javax/swing/plaf/synth/doc-files/componentProperties.html). For example, to paint radio buttons that are selected or unselected, use this code:
Synth's file format allows for embedding arbitrary objects by way of the long-term persistence of JavaBeans components . This ability is particularly useful in providing your own painters beyond the image-based ones Synth provides. For example, the following XML code specifies that a gradient should be rendered in the background of text fields:
In this lesson, we have covered the use of the javax.swing.plaf.synth package to create a custom look and feel. The emphasis of the lesson has been on using an external XML file to define the look and feel. The next lesson presents a sample application that creates a search dialog box using the Synth framework with an XML file.
This approach does look interesting, as it reduces considerably the burden required to get a LAF up-and-running, and is more analogous to skinnable applications like Winamp. There are of course performance issues to think about: a GUI consisting of images could well require additional resources, memory wise, although, with the improved graphics pipeline in the forthcoming Java release, this may not be an issue. A good example of a Synth-based LAF is Synthetica.
About the author:
Andrew Roberts is a computer science graduate from the University of Leeds, UK. He remained at Leeds to study further towards a PhD in Natural Language Processing. He has been using Linux for almost 8 years, and Java has been his language of choice for advanced language processing and machine learning during the last three years.
I understand your concern. The fact is developing a Swing application does not give you good performances for free. You have to know how Swing works. When you do, then you can use it wisely. The most common problem is related to event handling and the Event Dispatcher Thread (EDT). When you click on a button, your code runs in the EDT and if you perform long operations in this thread, you block the whole app. There are dozens of good documentation about how to work around this problem and it is very easy. When you do that correctly, 90% of the responsiveness problems disappear.
7fc3f7cf58