定义图 2 中登录屏幕例子的最后工作是用曲线绘制渐变背景。用 XML 来实现这种背景似乎有些别扭,坦白地说,真是这样。但这样我便有机会展示 Synth,不限制您在 UI 设计中只使用图像和简单的颜色。您可以使用它来画任何东西。
Synth 允许重写其 paint 方法(即在 javax.swing.plaf.synth.SynthPainter 类中的方法),该方法继承自 SynthPainter,它将覆盖那些您想要定制绘画方式的特定函数。在这个例子中,需要定义 paintPanelBackground 方法,因为这种设计不能以 Synth XML 格式描述。
为了使用定制的 painter,或者在 XML 中以任何方式创建一个类,可以使用标签。标签允许创建和保持用于弥补 Synth 呈现程序的任何 Java 类。标签带有两个元素
class :将创建的类的全名。
id :用于在 XML 文档中引用这个类实例的 ID 名。
通过使用对象,不仅可以创建 BackgroundPainter 类的实例 —— 这个类将用于绘制背景,而且还可以创建 ColorUIResource 类的实例,在这个类中可以定义背景颜色。想一想:在 BackgroundPainter 类中定义背景中使用的颜色,这与 Synth 的目标是矛盾的,Synth 的目标是在一个外部 XML 文件中定义一切,而不是在一个 Java 文件中进行硬编码。
使用定制 painter 的最后一步是告诉 Synth 呈现引擎,是您自己而不是 SynthPainter 类来提供函数。在这个例子中,首先在 BackgroundPainter 类中定义 paintPanelBackground 函数,并让 SynthPainter 类定义剩下的绘画函数。 标签让您可以覆盖 SynthPainter 函数。它带有两个元素:
method :定制 painter 应该覆盖的方法。从 使用图像 一节中您已经得知,您可以在 javax.swing.plaf.synth.SynthPainter 类中找到这些函数,但是应该删除每个函数开始部分的 paint 字符串(例如,SynthPainter 中的 paintPanelBackground 在 XML 文件中应该是 panelBackground)。
id:对将覆盖此方法的类的引用。
为了在定制 painter 中使用颜色,必须将颜色保存在 javax.swing.UIDefaults 类中。在清单 7 和清单 8 中可以看到,将颜色保存在 UIDefaults 中十分简单,对于那些接触过 UI 创建的人来说应该,应该比较熟悉这些内容。在 XML 文件中定义的键将成为 UIManager 中的引用,在 BackgroundPainter 的 Java 代码中,可以使用 UIManager 来获得颜色。
清单 7 展示了在例子应用程序中使用定制 painter 的 XML 代码。注意必须首先定义颜色。
清单 7. 使用定制 painter
2 <object id="background" class="demo.synth.BackgroundPainter"/>
3 <object class="javax.swing.plaf.ColorUIResource" id="startColor">
4 <int>30</int>
5 <int>123</int>
6 <int>235</int>
7 </object>
8 <defaultsProperty key="Panel.startBackground" type="idref" value="startColor"/>
9 <object class="javax.swing.plaf.ColorUIResource" id="endColor">
10 <int>1</int>
11 <int>20</int>
12 <int>80</int>
13 </object>
14 <defaultsProperty key="Panel.endBackground" type="idref" value="endColor"/>
15 <painter method="panelBackground" idref="background"/>
16 </style>
17 <bind style="panel" type="region" key="Panel"/>
清单 8 展示了例子应用程序的定制绘画类的 Java 代码:
清单 8. 定制绘画的 Java 代码
2 {
3 public void paintPanelBackground(SynthContext context,
4 Graphics g, int x, int y,
5 int w, int h)
6 {
7 Color start = UIManager.getColor("Panel.startBackground");
8 Color end = UIManager.getColor("Panel.endBackground");
9 Graphics2D g2 = (Graphics2D)g;
10 GradientPaint grPaint = new GradientPaint(
11 (float)x, (float)y, start,
12 (float)w, (float)h, end);
13 g2.setPaint(grPaint);
14 g2.fillRect(x, y, w, h);
15 g2.setPaint(null);
16 g2.setColor(new Color(255, 255, 255, 120));
17 g2.setRenderingHint(
18 RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
19 CubicCurve2D.Double arc2d = new CubicCurve2D.Double(
20 0, h/4, w/3, h/10, 66 * w, 1.5 * h, w, h/8);
21 g2.draw(arc2d);
22 g2.setRenderingHint(
23 RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
24 }
25 }