简体   繁体   中英

How to make a lightweight Swing or AWT component translucent in Java

A while ago, I tried to implement a semitransparency method for Swing/AWT components, and just now tried it out for the first time. However, several glitches in the UI surface upon implementation. The code of the method is below:

  public static void setTransparency(Component comp, float t)
  {
    try
    {
      if (comp instanceof Window)
      {
        try
        {
//For JDK 1.7
          ((Window) comp).setOpacity(t);
        }
        catch (Throwable th)
        {
          System.err.println("JRE may be less than 1.7!");
          if (!th.getClass().isInstance(new NoSuchMethodError()))
            th.printStackTrace();
          try
          {
//For JDK 1.6
            com.sun.awt.AWTUtilities.setWindowOpacity((Window) comp, t);
          }
          catch (Throwable th1)
          {
            throw new UnsupportedOperationException("It seems that transparency is not supported", th1);
          }
        }
      }
      else
      {
        if (comp instanceof JComponent)
          ((JComponent)comp).setOpaque(false);
        Graphics2D g2 = (Graphics2D) comp.getGraphics().create();
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, t));
        comp.paint(g2);
        g2.dispose();
      }
    }
    catch (Throwable th)
    {
      throw new UnsupportedOperationException("Transparency might not be supported", th);
    }
  }

When run, the component does not change in appearance. Does anyone have a suggestion for making a Swing or AWT component semitransparent that is 100% reliable? This only applies to lightweight components, as heavyweight transparency is separately covered and 100% reliable, as shown above.

Ah, you might wan to look at JLayer (or JXLayer for < Java 1.7) for transparency then.

See the tutorial

Well, here's your first problem:

Graphics2D g2 = (Graphics2D) comp.getGraphics().create();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, t));
comp.paint(g2);
g2.dispose();

You should only be painting components inside a call to paint(Graphics g) . Painting during a call to your setTransparency method is A Bad Idea, because it will be erased the next time Swing decides to call paint . You need to make your component handle it's own transparency inside the paintComponent method.

Also this: if (!th.getClass().isInstance(new NoSuchMethodError()))

What on earth are you doing? What's wrong with a simple catch (NoSuchMethodError e) ? Or, if you really want to use instanceof then th instanceof NoSuchMethodError ?

By the way, @WalterLaan and @JimN know what they're talking about. setOpaque (or, more accurately, isOpaque ) is a rendering hint to the Swing engine that can help it optimize it's operation. Check the javadocs and you'll see what I mean. It's nothing to do with turning the background on or off. Well, that's not entirely true - JComponent , by default, does some cleverness with the opaque property to automatically paint the background if appropriate, but if you're handling your own painting then that cleverness will probably be overridden.

EDIT: Regarding the NoSuchMethodError. Take a look at this:

void setTransparency(Window w, double t) {
    try {
        setOpacity17(w, t);
        return;
    }
    catch (NoSuchMethodError e) {
        System.err.println("JRE *is* less than 1.7!"); // We know the JRE must be < 1.7 because the right methods are known to exist in 1.7.
    }
    catch (Throwable t) {
        t.printStackTrace();
    }
    try {
        setOpacity16(w, t);
    }
    catch (Throwable t) {
        System.err.println("Boom!");
    }
}

void setOpacity17(Window w, double t) {
    ...
}

void setOpacity16(Window w, double t) {
    ...
}

That's a lot cleaner. Note the return that will short-circuit the function if the 1.7 version succeeds.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM