Helping ordinary people create extraordinary websites!

Advanced Synth

By Michael Abernethy
2005-04-16

Working with Custom Painters
The final piece to defining the example login screen in Figure 2 is to draw the gradient background with the curved line. This probably looks tough to do in XML, and frankly it is. But it gives me a chance to show that Synth doesn't limit you to using only images and simple colors in UI designs. You can use it to draw anything.

Synth lets you override its paint methods (the ones in javax.swing.plaf.synth.SynthPainter) by subclassing SynthPainter and overriding only the specific functions you wish to custom paint. In the example, you need to custom paint the paintPanelBackground method, because the design can't be described in the Synth XML format.

To use a custom painter, or to create a class in any way in the XML, you use the <object> tag. The <object> tag allows for creation and persistence of any Java classes you want to use to supplement the Synth rendering. The <object> tag takes two elements:

• class: The full name of the class that should be created
• id: The ID name you'll use to reference this class instance in the XML document

By using objects, you not only can create the instance of the BackgroundPainter class -- the class that will paint the background. You can also create an instance of a ColorUIResource class, where you define the background colors. Think about it: Defining the colors used in the background inside the BackgroundPainter class itself would contradict Synth's goal of defining everything in an external XML file rather than hard-coding it in a Java file.

The final step to using a custom painter is to tell the Synth rendering engine that you, not the SynthPainter class, will be supplying the function. In the example, you define the paintPanelBackground function in the BackgroundPainter class and let Synth use its SynthPainter class to define the rest of the paint functions. The <painter> tag lets you override the SynthPainter function. It takes two elements:

• method: The method that the custom painter should override. As you know from Using images, you can find these functions in the javax.swing.plaf.synth.SynthPainter class but should remove the paint string at the beginning of each function. (So paintPanelBackground in SynthPainter should be panelBackground in the XML file, for example.)

• id: The reference to the class that will override the method.

In order to use the colors in the custom painter, you must store them in the javax.swing.UIDefaults class. As you can see in Listings 7 and 8, storing colors in UIDefaults is straightforward and should be familiar to anyone who's worked with UI creation. The key you define in the XML will be the reference in the UIManager you use to get the colors in the actual Java code for BackgroundPainter.

Listing 7 shows the XML code for working with custom painters in the example application. Notice that you must define the colors first.

Listing 7. Working with custom painters

<style id="button">

<state>
<imagePainter method="buttonBackground" path="images/button.png"
sourceInsets="9 10 9 12" paintCenter="true" stretch="true"/>
<insets top="9" left="10" bottom="9" right="12"/>
<font name="Aharoni" size="16"/>
<color type="TEXT_FOREGROUND" value="#FFFFFF"/>
</state>
<state value="MOUSE_OVER">
<imagePainter method="buttonBackground" path="images/button_on.png"
sourceInsets="9 10 9 12" paintCenter="true" stretch="true"/>
<insets top="9" left="10" bottom="9" right="12"/>
<color type="TEXT_FOREGROUND" value="#FFFFFF"/>
</state>
<state value="PRESSED">
<imagePainter method="buttonBackground" path="images/button_press.png"
sourceInsets="10 12 8 9" paintCenter="true" stretch="true"/>
<insets top="10" left="12" bottom="8" right="9"/>
<color type="TEXT_FOREGROUND" value="#FFFFFF"/>
</state>
<property key="Button.margin" type="insets" value="0 0 0 0"/>
</style>
<bind style="button" type="region" key="Button"/>
Listing 8 shows the Java code for the example application's custom-painting class:

Listing 8. Java code for custom painting

public class BackgroundPainter extends SynthPainter

{

public void paintPanelBackground(SynthContext context,
Graphics g, int x, int y,
int w, int h)
{
Color start = UIManager.getColor("Panel.startBackground");
Color end = UIManager.getColor("Panel.endBackground");
Graphics2D g2 = (Graphics2D)g;
GradientPaint grPaint = new GradientPaint(
(float)x, (float)y, start,
(float)w, (float)h, end);
g2.setPaint(grPaint);
g2.fillRect(x, y, w, h);
g2.setPaint(null);
g2.setColor(new Color(255, 255, 255, 120));
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
CubicCurve2D.Double arc2d = new CubicCurve2D.Double(
0, h/4, w/3, h/10, 66 * w, 1.5 * h, w, h/8);
g2.draw(arc2d);
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
}
}




Tutorial pages:

First published by IBM DeveloperWorks


 2 Votes

You might also want to check these out:


Leave a Comment on "Advanced Synth"
You must be logged in to post a comment.

Link to This Tutorial Page!


GET OUR NEWSLETTERS