Using Swing with Java 3D

The Java Swing API is a nearly exhaustive collection of user interface widgets that can be used to build a user interface around a Java 3D application. There are some real challenges to mixing Swing and Java 3D components. This is largely because Swing components are lightweight whereas the Java 3D Canvas3D component is heavyweight.

Lightweight Versus Heavyweight

The difference between lightweight and heavyweight components is a bit obscure. Simply stated, heavyweight components reference their own native screen resource called a peer. A lightweight component has no native peer and therefore temporarily uses the resources of a nearby native peer.

In general, lightweight UI components have many advantages including having a smaller resource footprint and also the ability to maintain a consistent look and feel across platforms. The downside is that some components do not have lightweight versions; therefore, it becomes necessary to mix lightweight and heavyweight. This is the exact situation that happens when we want to use the heavyweight Canvas3D object (which, as you know, is necessary to view our 3D scene) in conjunction with Swing components. There is no lightweight version of the Canvas3D object.

We should note that several of the Swing components are indeed heavyweight by design. In particular, the top-level components JWindow, JFrame, JApplet, and JDialog are all heavyweight. These components can be mixed with a Canvas3D object without concern. All AWT components are heavyweight as well.

Mixing Problems

Three main problems occur when mixing heavyweight and lightweight components:

  • Mouse events for lightweight components filter up to the heavyweight parent, whereas mouse events for heavyweight components do not.

  • Heavyweight components always appear on top of lightweight components regardless of the z order in which they are rendered.

  • Lightweight components can have transparent pixels, whereas heavyweight components do not.

This section focuses on the second and third problems, which are of the most concern in Java 3D. The first problem does not interfere with the working of Java 3D in general, and thus won't be discussed further.

Returning to the second and third problems, we can see issues with the display of the Canvas3D. A partial solution to these display problems can be solved by avoiding certain situations or, alternatively, setting a flag to override lightweight functioning of the component.

First and foremost, avoid mixing lightweight and heavyweight components. This can be accomplished by keeping the heavyweight components in an area of the screen where lightweight components are not expected to overlap.

Also in terms of mixing components, certain lightweight components should never have a heavyweight component added to them. The two most common examples of this are adding a Canvas3D to a JInternalFrame or JScrollPane.

The same problems can occur when using pop-up components such as JComboBox or JPopupMenu. In this case, Java determines what the ideal weight of these objects should be in the context of the application. This decision is dependent on whether a property called LightWeightPopupEnabled is set to true or false. For example, if a JPopupMenu is activated, it can be heavyweight if the component does not fit entirely in its container, mediumweight if the pop-up fits within the top-level component but the lightweightPopupEnabled property is set to false, or truly lightweight if the pop-up fits within the top-level component but lightweightPopupEnabled is set to true (the default).

Therefore, you can set the LightWeightPopupEnabled property to false to ensure that the component is heavyweight. There are two methods for setting this property—one global (applies to all pop-ups) and the other more restricted (on a pop-up by pop-up basis).

The global method is

public static void setDefaultLightweightPopupEnabled(boolean)

To change the property for an individual pop-up component, use the following:

public void setLightweightPopupEnabled(Boolean)

The BadMix.java example in Listing 12.14 illustrates the preceding two approaches to mixing heavy- and lightweight components.

Listing 12.14 BadMix.java
. . .
public class BadMix extends JFrame {
  VirtualUniverse universe;
  Locale locale;
  TransformGroup vpTrans;
  View view;
  Bounds bounds;

    public BranchGroup createSceneGraph() {
        // Create the root of the branch graph; this will be returned
        Appearance app = new Appearance();
        BranchGroup objRoot = new BranchGroup();

        TransformGroup geoTG = new TransformGroup();
        geoTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    geoTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);

        BoundingSphere bounds =
             new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);

        MouseRotate mouseBeh = new MouseRotate(geoTG);
    geoTG.addChild(mouseBeh);
    mouseBeh.setSchedulingBounds(bounds);


        geoTG.addChild(new Box(.5f,.5f,.5f,app));
        objRoot.addChild(geoTG);

        //objRoot.addChild(pc.getShape());
       // objRoot.addChild(tc.getShape());


        Color3f blue = new Color3f(0.f, 0.9f, 0.f);
        Vector3f bluedir  = new Vector3f(0.0f, -8.0f, -8.0f);


       // AmbientLight al = new AmbientLight(true, new Color3f(.1f,.9f, .1f));
        AmbientLight al = new AmbientLight();

        DirectionalLight bluelight = new DirectionalLight(blue, bluedir);

        al.setInfluencingBounds(bounds);
        bluelight.setInfluencingBounds(bounds);

        objRoot.addChild(al);

       objRoot.addChild(bluelight);

        objRoot.compile();
    return objRoot;
     }

. . .

    public BadMix(int xsize, int ysize) {

. . .
        c.setSize(90,900);
        JScrollPane jscroll = new JScrollPane(c);
        jscroll.setPreferredSize(new Dimension(2, 1));


    JScrollBar scrollv = new JScrollBar(JScrollBar.VERTICAL);
    scrollv.setBounds(129,4,13,97);
    scrollv.setForeground(new Color(-987431));

        JScrollBar scrollh = new JScrollBar(JScrollBar.HORIZONTAL);
    scrollh.setBounds(129,4,13,97);
    scrollh.setForeground(new Color(-987431));

       JMenuBar menubar= new JMenuBar();
       setJMenuBar(menubar);

       JMenu menu1 = new JMenu("Heavyweight Menu");
       menubar.add(menu1);
       JMenu menu2 = new JMenu("Lightweight Popup");
       menubar.add(menu2);


       String[] jazzPlayers = { "Bird", "Monk", "Coltrane", "Dizzy", "Miles" };
       JComboBox jcombo = new JComboBox(jazzPlayers);

       this.getContentPane().add(jcombo, BorderLayout.NORTH);

       jcombo.setLightWeightPopupEnabled(false);


       menu1.add(new JMenuItem("Heavyweight; Should see this! "));
        menu1.add(new JMenuItem("Heavyweight; Should see this!! "));
        menu1.add(new JMenuItem("Heavyweight; Should see this!! "));


        JPopupMenu popup = menu1.getPopupMenu();
        popup.setLightWeightPopupEnabled(false);

       menu2.add(new JMenuItem("Lightweight; Cannot see parts overlapping heavyweight! 
"));
       menu2.add(new JMenuItem("Lightweight; Cannot see parts overlapping heavyweight!! 
"));
       menu2.add(new JMenuItem("Lightweight; Cannot see parts overlapping heavyweight!!! 
"));

       int num_menus = menubar.getMenuCount();
       System.out.println(num_menus);

. . .

        jscroll.add(scrollv);
        jscroll.add(scrollh);
        locale.addBranchGraph(vgraph);
    locale.addBranchGraph(scene);
    }

    //
    // The following allows HelloUniverse to be run as an application
    // as well as an applet
    //
}
						

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset