"Transparent" Panel - Mixing Heavyweight and Lightweight Components Blog

Version 2

    When overlaying lightweight Swing widgets on top of heavyweight AWT components, it is convenient to group the Swing widgets on a transparent (non-opaque) JPanel so that one can use Swing layout managers and/or Swing utilities on a group o f related Swing widgets. For example, all widgets added to the transparentJPanel can be made visible or invisible simultaneously with one setVisible() call on the JPanel. Unfortunately, a lightweight JPanel overlaid on top of a heavyweight AWT component cannot be transparent.

    To overcome this problem, one can implement aTransparentPanel as shown below.

     public class TransparentPanel extends JPanel { /** * Default constructor. Sets the layout manager to JPanel's * default layout manager: FlowLayout. */ public TransparentPanel() { this(new FlowLayout()); } /** * Construct panel with input layout manager. * * @param mgr The layout manager for the extended JPanel. */ public TransparentPanel(LayoutManager mgr) { // set layout manager, if any super(mgr); // set opaque false so that an isOpaque() == false super.setOpaque(false); // set mixing cutout -- see AWTUtilitesClass below AWTUtilitiesClass.setMixingCutoutShape(this, new Rectangle()); } /** * Override setOpaque so that the user cannot change the * opacity of this panel, since it is after all suppose to * be transparent. * * @param isOpaque Is this panel opaque? */ @Override public void setOpaque(boolean isOpaque) { // do not allow this to become opaque because it is // transparent after all } }

    Note that the constructor of TransparentPanelinvokes AWTUtilitiesClass.setMixingCutoutShape(). Invoking AWTUtilitiesClass.setMixingCutoutShape() is necessary to avoid non-rendering of ourTransparentPanel which would result in a solid gray (and not transparent!) TransparentPanel. The AWTUtilitiesClass "mixing cutout" technique is described in Mixing Heavyweight and Lightweight Components, October 2009 by Sharon Zakhour and Anthony Petrov, whose code has been excerpted below:

     public class AWTUtilitiesClass { private static Method mSetComponentMixing; static try { Class awtUtilitiesClass = Class.forName("com.sun.awt.AWTUtilities"); Method mSetComponentMixing = awtUtilitiesClass.getMethod( "setComponentMixingCutoutShape", Component.class, Shape.class); mSetComponentMixing.invoke(null, component, shape); } catch (Execption ex) { ex.printStackTrace(); } public static void setMixingCutoutShape(Component c, Shape s) { if (mSetComponentMixing != null) { try { mSetComponentMixing.invoke( null, c, s ); } catch (Exception ex) { ex.printStackTrace(); } } } }

    Real World Example: Mixing Swing and Java WorldWind - Software vs Hardware Acceleration

    When developing Java WorldWindapplications, it is typical for the developer to overlay aJPanel (which contains Java Swing GUI components) above a WorldWind Java container (which contains the rendered world). The WorldWind Java container is usually (1) aGLJPanel which is a subclass of the lightweight SwingJPanel, or (2) a GLCanvas which is a subclass of the heavyweight AWT Canvas.

    If Option 1, GLJPanel, is utilized, then the Java WorldWind developer (a) maintains the ability to overlay transparent Swing components above the world (that is, theGLJPanel). However, when attempting to turn on software acceleration, the developer will often find that doing so (b) creates run time exceptions that are difficult if not impossible to overcome, and (c) the performance gained is inferior to performance gains of hardware acceleration.

    If Option 2, GLCanvas, is utilized, then the Java WorldWind developer (a) loses the ability to overlay transparent Swing components above the world (that is, theGLCanvas). However (b) runtime exceptions are not experienced, and (c) the performance gained is superior to software acceleration. Additionally, the TransparentPanelintroduced in this article coupled with the "mixing cutout" from A. Petrov's article restores the ability for the Java WorldWind developer to maintain inter-component transparency, thus partially alleviating the problems of (a) and more readily allowing the Java WorldWind developer to combine lightweight Swing overlays (containing "grouped" Swing widgets) with heavyweight hardware acceleration.


    During development, when using Java Swing components rendered in an overlay above a Java WorldWind layer, a predictable gray flash (flicker) was detected. To alleviate this problem, one can utilize the flag:


    If one wishes to override the paint() method of aTransparentPanel subclass such that the subclass uses Java2D to draw a Shape onto the superclassTransparentPanel, then the "mixing cutout" described above can cause the TransparentPanel and anything drawn on it to vanish. To resolve this, instead of passing the empty Shape via new Rectangle() toAWTUtilitiesClass.setMixingCutoutShape(), one should pass the shape of the desired drawing. See Mixing Heavyweight and Lightweight Components, October 2009.

    If one wishes to overlay a non-rectangular lightweight component above a heavyweight component, one must bear in mind that JavaShapes (and thus "mixing cutouts") cannot be anti-aliased, so for non-rectangular Swing components, one must smooth the non-aliased "mixing cutouts" using hues or blurring.