Add a Third Dimension to Swing #63
Chapter 8, Rendering
|
319
HACK
As you can see, you end up with a black background in the Canva3D. Because
the only way to get rid of a component’s background is to call
setOpaque(false)
—which is defined by
JComponent
and thus isn’t available
to AWT components—you are stuck with this ugly background. Indeed, as
a lightweight component, the canvas cannot be made transparent. Things
get even worse when you try to add a menu bar to the application because of
the order in which components are painted: lightweight first, heavyweight
next. Figure 8-10 shows an example of what happens when a pop-up menu
is drawn by Swing. Because it is a lightweight component, it is drawn before
Canvas3D
, when it should be drawn after the canvas.
Thankfully, this new problem (it’s all AWT’s fault!) was so annoying that
the Swing team decided to add a workaround for it. You can simply force all
pop-up menus of your applications to be created as heavyweight compo-
nents instead of lightweight components. A single line of code is enough to
fix the problem:
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
If you invoke this method before you create the first JMenu or JPopupMenu,
you ensure your menus will be drawn on top of heavyweight components.
So, this takes care of one issue, but you still need to deal with the black
background problem.
Faking Transparency
Because you cannot change the opacity of the Canvas3D, you are left with
only two possible solutions. The first is to get rid of Swing, go back to AWT,
and offer a crappy interface to the users. Because this doesn’t seem like too
great an option, we’ll just have to fake transparency.
Figure 8-10. Lightweight components are drawn behind heavyweight components
320
|
Chapter 8, Rendering
#63 Add a Third Dimension to Swing
HACK
A Java3D scene is represented as a graph in which every node is an object or
a group of objects. A close look at the package
com.sun.j3d.utils.geometry
reveals the existence of the
Background
class, which you can use to change
the background of the 3D scene. For instance, you can create an Alpine
scene just by adding a background with a photo of the Alps as its texture.
Therefore, to fake transparency, you just have to use the window’s content
panel as texture for a new
Background object that you then add to the scene
graph. This is how AmazonPick creates the Java3D scene and adds a special
background:
public void createScene( )
{
BranchGroup objRoot = new BranchGroup( );
objRoot.addChild(createBackground( ));
// creates the whole scene
}
In Java3D, the scene is an instance of BranchGroup. By adding the Background
created by the method createBackground( ) as a child of the scene node, you
can set the background of the scene. The background itself is created like
this:
protected Background createBackground( )
{
BufferedImage image;
image = new BufferedImage(c3d.getParent().getWidth( ),
c3d.getParent().getHeight( ),
BufferedImage.TYPE_INT_RGB);
getContentPane().paint(image.getGraphics( ));
BufferedImage subImage;
subImage = new BufferedImage(CANVAS3D_WIDTH,
CANVAS3D_HEIGHT,
BufferedImage.TYPE_INT_RGB);
Graphics2D subGraphics = (Graphics2D) subImage.getGraphics( );
subGraphics.drawImage(image, null, -c3d.getX(), -c3d.getY( ));
ImageComponent2D backImage;
backImage = new ImageComponent2D(ImageComponent2D.FORMAT_RGB,
subImage)
Background bg = new Background(backImage);
BoundingSphere bounds = new BoundingSphere( );
bounds.setRadius(100.0);
bg.setApplicationBounds(bounds);
return bg;
}
The texture is created in two steps. The first is to create a BufferedImage
called image on which you paint the content panel of the window. Notice
that the picture has the same dimensions as the content panel. Calling the

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.