Tutorials

Sections

j3d.org

Integrating Java 3D and Swing

By Karl Meissner

A way to leverage J3D is to integrate it into a Swing GUI environment. This allows the application to have the various standard buttons, sliders and menu popups with J3D being rendered to a child window in the application.

The basic trick is to add a Canvas3D to a JPanel. Now a scene can be put in a GUI as needed.

The integration between Swing and J3D is not perfect. There are overdraw issues and texture management issues. With careful design, most of these problems can be worked around.

Here are some of the issues to contend with.

Swing basics

Swing is lightweight and J3D is heavy weight. This means that a Canvas3D will draw on top of Swing objects no matter what order Swing thinks it should draw in.

From Sun's Mixing heavyweight and lightweight components

A heavyweight component is one that is associated with its own native screen resource (commonly known as a peer). A lightweight component is one that "borrows" the screen resource of an ancestor (which means it has no native resource of its own -- so it's "lighter")."
Swing popup menus do work with J3D. The Swing teams added a flag which forces menus to be heavyweight.
    JPopupMenu.setDefaultLightWeightPopupEnabled( false );
This will change the global static default so all new popup menus are heavy. Note you must set the default before the popup is instantiated for this to take effect.

Using other Swing containers

At some future release these may be fixed.

Overdraw is very apparent for JInternalFrames. JInternalFrames with J3D will have the J3D part incorrectly draw on top. Instead of using JInternalFrames to hold J3D, you should keep your J3D in fixed locations on screen where Swing objects can not be on top of them.

If have got to have multiple scenes, JTabbedPanes are useful for this as long as you only put J3D in the JTabbedPane and not any Swing elements.

If you need to scroll a J3D scene, a Swing JScrollPane will not work. You will need to use the AWT ScrollPanel.

Updating components within a J3D Behaviour locks the application

Swing uses its own internal threading mechanism to send threads that can cause deadlocks within the Java3D scheduling system. That is, trying to change them from any thread other than as a result of an EventListener is almost guaranteed to lock up your application GUI. If you need to update swing based components from within a thread, you will want to check out the APIs javax.swing.SwingUtilities.invokeAndWait(Runnable) or invokeLater() to update components from a different thread.

Text2D bug

In J3D version 1.2.1_01 OpenGl on Windows, there is a bug in Text2D objects in JInternalFrames. (besides the overdraw problems). Clicking on several JInternalFrames with different scenes corrupts the textures of the Text2D and they start to draw as white polys. This does not seem to happen when the scenes are in other Swing containers, but the extent of the problem is unknown.

JTabbedPane

When a JTabbedPane is created with J3D scenes, the select tab is not synced with the top most Canvas3D until the user clicks on the tab. You must manually set the tab to be what ever the top most Canvas3D happens to be with this.setSelectedIndex(). Once the user clicks on the tabs, they sync up.

The j3d_in_swing code illustrates these issues and points to several workarounds that can hide the problems from the users. Several Swing windows are created with a 3D scene. The scenes can be rotated with a left mouse click and drag. The internal frames on the desktop show some of the overdraw issues. The tabbed pane probably works best with J3D. See also my page dealing with Swing and Java3D