278
|
Chapter 7, Text
#53 Use Global Anti-Aliased Fonts
HACK
There is no definitive list of every CSS layout feature the HTMLEditorKit sup-
ports, but you can get a good overview in the JavaDoc for the
javax.swing.
text.html.CSS
class.
CSS also gives you the ability to define a style and reuse it with multiple
components, putting you one step closer to the kind of separation of con-
tent and style that we take for granted on the Web. In this example, both
labels share the same CSS declaration. If you change the declaration, it
would change both labels. This declaration could even be stored in a proper-
ties file, letting non-programmers affect the look of your application:
StringBuffer css = new StringBuffer( );
css.append("<html><head><style type='text/css'>");
css.append("body { color: #4444ff; font-weight: normal;}");
css.append("</head><body>");
JLabel l4 = new JLabel(css+"Cartman");
JLabel l5 = new JLabel(css+"Stan");
This produces the labels seen in Figure 7-17.
Putting HTML in Swing components is a little-known feature that packs a
big punch. You can use it to quickly create layout effects that are cumber-
some or impossible to do with traditional text.
H A C K
#53
Use Global Anti-Aliased Fonts Hack #53
Think Swing apps always look ugly because of the chunky fonts? Finally, you
can do something about it!
Java 1.2 introduced Java2D, complete with the ability to draw anti-aliased
text. Unfortunately, anti-aliasing is off by default and turning it on requires a
programmatic change on each UI component. This hack shows how to turn
on anti-aliasing for an entire frame without customizing each component. It
also introduces a special repaint manager that is the key to several other
hacks in this book, such as the partial translucent menus
[Hack #12].
The Problem
To turn on anti-aliasing, you simply need to set a rendering hint:
Figure 7-17. Shared CSS styles
Use Global Anti-Aliased Fonts #53
Chapter 7, Text
|
279
HACK
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Unfortunately, the
Graphics
object is not very long-lived. There is no global
place to set a hint because there’s a new
Graphics
object for every
repaint( )
.
Any property you set would be gone by the next paint call. The usual
workaround is to subclass the component you want to anti-alias and over-
ride the
paint( ) method:
class AAButton extends JButton {
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
super.paint(g2);
}
}
This will work, but it means you have to create a custom subclass for every
component in your application. Not a very appealing solution.
Mac OS X provides anti-aliased rendering through a system property, but
this only works because Apple thoughtfully added it to their JVM. Develop-
ers on other platforms are left out. Java 5.0 provides a standard system prop-
erty for anti-aliasing, but that doesn’t help the millions of 1.3 and 1.4 JVMs
out there. Another option would be to use some form of code injection to
modify each paint method at the bytecode level, but this requires an AOP
tool, custom build scripts, and other things that are probably overkill for
such a simple feature. There has to be a better way—and there actually is.
A long, long time ago (in a research lab far, far away) I worked on a scalable
UI toolkit for Java called SubArctic. One of its key features was that a com-
ponent would paint onto a canvas object called a
Drawable—what we would
call a
Graphics object in Swing. This Drawable would be passed from parent
to child in a recursive tree traversal.
Drawables could be hacked to do all
sorts of complicated things, and since a child always drew on the
Drawable
from its parent, the parent could make a change without the child knowing
about it. Thus, you could create a parent panel that rotated all graphics by
45 degrees and a standard child component (like a button or scrollbar)
would work without modification. This scheme was incredibly flexible. We
had hacks for drop shadows, bit-level operations (blur, sharpen, b/w), affine
transformations (rotate, shear), or just about any other crazy idea you could
come up with. I have long wanted to do this in Swing, but there has always
been one obstacle: in Swing, a child’s
paint( ) method is not always called
by its parent’s
paintChildren( ) method.

Get Swing Hacks now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.