324
|
Chapter 8, Rendering
#64 Turn the Spotlight on Swing
HACK
You can even go one step further: the more light you shed, the less darkness
there is. For instance, when several books are found, it is likely that the
search query was not very precise. This means the user will be more inter-
ested in lots of items. When the query yields only a few results, it is likely
that the user wants to see only a few specific items.
As you create several spotlights—one per result—the interface is less dark-
ened than with only one spotlight. If you take a close look at Figure 8-13,
you’ll be able to perceive the other books. Nevertheless, a single search
result will prevent the user from seeing the other books, as shown in
Figure 8-14.
Add the Spotlight
The implementation of spotlights for Swing is divided into two classes,
SpotlightPanel and Spotlight. The first class is a glass pane that needs to be
set up on a frame, and the second defines the location and the shape of a
spotlight. Here is an example of how to use spotlights:
SpotlightPanel glassPane = new SpotlightPanel( );
setGlassPane(glassPane);
Spotlight s1 = glassPane.addSpotlight(0, 0, 25, 50);
Spotlight s2 = glassPane.addSpotlight(100, 100, 30);
Figure 8-14. With only one spotlight, it is almost impossible to see the other books
Turn the Spotlight on Swing #64
Chapter 8, Rendering
|
325
HACK
Here, you create two spotlights: s1 and s2. The first is an ellipse 25-pixels
wide, 50-pixels high, and located at the top-left corner of the frame; the sec-
ond is a circle with a radius of 30 pixels and located 100 pixels away from
the top and the left of the frame’s border. Each spotlight is implemented as
an ellipse with the class
Ellipse2D.Double
, as shown in Example 8-11.
As you can see in the code, the
Spotlight class is fairly simple and contains
only two public methods. The first one,
getSpot( ), returns the Ellipse2D
instance used to draw the spotlight. It can also be used to dynamically
change the location and the size of the spotlight. Once you’ve installed a few
spotlights, you will be able to get
Ellipse2D to animate them. By moving
them around, shrinking them, or growing them, you can create stunning
effects. The second method of this class,
getArea( ), is used by
SpotlightPanel to define the amount of darkness according to the total area
occupied by the spotlights on the window. Thus, if you have enough spot-
lights to cover 80% of the window with light,
SpotlightPanel will use a
darkness of 20%. In short,
getArea( ) computes the geometrical area of the
spotlight’s ellipse.
The
SpotlightPanel panel class (shown in Example 8-12) only needs a few
methods as well. You must be able to create spotlights, to remove a particu-
lar spotlight, to remove all spotlights, and to paint spotlights on the screen.
You also need two constructors. If you look at the previous figures, you
should see that the spotlights’ borders are blurred to get a nicer rendering.
Example 8-11. Representing a spotlight with an Ellipse2D
public class Spotlight
{
protected Ellipse2D.Double spot;
protected Rectangle2D.Double bounds;
public Spotlight(int x, int y, int w, int h)
{
this.spot = new Ellipse2D.Double(x, y, w, h);
}
public Ellipse2D getSpot( )
{
return spot;
}
public double getArea( )
{
return Math.PI * spot.getWidth() * spot.getHeight( ) / 4.0;
}
}
326
|
Chapter 8, Rendering
#64 Turn the Spotlight on Swing
HACK
Unfortunately, the blurring method used in the painting algorithm is very
slow and prevents smooth animation of the spotlights. To account for this,
you need a special constructor to instruct the panel to draw blurred borders,
along with a constructor that leaves blurring at its default (on in this class,
although you may want to leave it off normally). When you need still spot-
lights, activate the blur to get a nicer result. On the contrary, when you want
to animate the spotlights, deactivate the blur to get full-speed animations.
The default constructor enables the blur. You can use the second construc-
tor and pass it
false to deactivate this option. The rendering of the blur
effect is done with the help of a
ConvolveOp. You learned about the inner
workings of a blur operation when you blurred disabled components
[Hack #9].
The constructor also creates an instance of
ArrayList in which all the spot-
lights are stored:
public Spotlight addSpotlight(int x, int y, int w, int h)
{
if (spotlights.size( ) == 0)
{
Example 8-12. Constructors of the SpotlightPanel class
public class SpotlightPanel extends JComponent implements MouseListener
{
protected boolean blur;
protected List spotlights;
protected ConvolveOp blurOp;
protected RenderingHints hints;
public SpotlightPanel( )
{
this(true);
}
public SpotlightPanel(boolean blur)
{
this.blur = blur;
spotlights = new ArrayList( );
blurOp = new ConvolveOp(getBlurKernel(3), ConvolveOp.EDGE_NO_OP, null);
hints = new RenderingHints(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
hints.put(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
hints.put(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
}
// other methods omitted
}

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.