Custom Look&Feel in Java

The first question to why you feel you need to create your own Look and feel (L&F). I guess you did that and came up with a good enough reason and now you are questioning yourself how to go about to achieve this. This articles gives some pointers that I came across while I implemented the custom Look and Feel for OpenPatrician. These are especially points that I found nowhere on the web mentioned and I had to figure it out the hard way.

There are basically two different ways to create a custom L&F. Both however are based on an existing L&F. This can either be the <code>BasicLookAndFeel</code> or more commonly a subclass thereof.

  1. You want to change the look of the application. Typically this includes: usage of color, fonts, indention and borders. All this can be achieved through themeing or by a simple L&F class that overrides the default values.
  2. The application should have its own Feel. This may include beside the above the handling of events and look of the components itself.

First some articles that are out there that helped me starting:

Most of the time I find it instructive to look at some code to learn how it is done (if there are no easier ways around to learn this, and with L&F this sadly is the case). Here is a collection of some L&Fs free and commercial.

In my current game project (OpenPatrician, I don’t know if I mentioned it before), there are some screens that have actually a form on it (load, save, new, …) These forms however should integrate in the Look and Feel of the game, which is done without any swing/awt components. Therefore the existing L&F did just not work. Writing a L&F from scratch (or even upon an existing L&F) is much work. Therefore I decided which components I needed in my game and created for this subset a custom Look and Feel.

No static references

The L&F I took as an example used static references as a means to save memory. This works fine for simple components (label, button) or if there is only one instance of this component available in the GUI. In all other cases this is bad because each component references the L&F instance as it is set up for the last component. I had different spinners in my form with different data, however all spinners showed the data from the last. Therefore do not use static references.

The methods

Commonly you will override at least these four methods:

  • The static method createUI(JComponent) which will return an instance of the L&F class
  • installUI(JComponent) where you initialize your instance (registering listeners)
  • uninstallUI(JComponent) the reverse of the installUI method
  • paint(Graphics, JComponent): Here you will implement the drawing of the component

Drawing back to front

As usual you will start the drawing with the layers in the back. However if your component is transparent and it changes its appearance this may pose a problem. Here it may be simpler to store the image that is behind the component before the first drawing and use this as an additional layer and thus realizing the transparency.

Composed components

I had to learn that there are components that are composed from other components. The Spinner for example is composed by two buttons and an editor that is implemented as formatted text field. When customizing such a component you must consider customizing its child components. This may cause conflicts because these component may have a different look when they are used on their own.

Sizing

If you have overridden the paint method you probably should override the getPreferredSize(JComponent) method for proper sizing. This method will probably called when the layout manger defines the layout. If the preferred size on the component is not set the L&F is asked to provide the dimensions.

Schreibe einen Kommentar