如何在 Java 中使轻量级 Swing 或 AWT 组件半透明

发布于 2024-12-21 05:21:07 字数 1374 浏览 6 评论 0原文

前段时间尝试为Swing/AWT组件实现半透明的方法,现在才第一次尝试。然而,在实施过程中,UI 中出现了一些问题。该方法的代码如下:

  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);
    }
  }

运行时,组件的外观没有变化。 是否有人建议将 Swing 或 AWT 组件设为半透明且 100% 可靠? 这仅适用于轻量级组件,因为重量级透明度是单独覆盖的且 100% 可靠,如上所示。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

为你鎻心 2024-12-28 05:21:07

啊,那么您可能想查看 JLayer(或

请参阅教程

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

See the tutorial

梦言归人 2024-12-28 05:21:07

好吧,这是您的第一个问题:

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

您应该只在调用 paint(Graphics g) 内绘制组件。在调用 setTransparency 方法期间进行绘制是一个坏主意,因为下次 Swing 决定调用 paint 时它将被删除。您需要让组件在 paintComponent 方法中处理它自己的透明度。

还有这个: if (!th.getClass().isInstance(new NoSuchMethodError()))

你到底在做什么?简单的 catch (NoSuchMethodError e) 有什么问题?或者,如果您真的想使用instanceof,那么第一个instanceof NoSuchMethodError

顺便说一句,@WalterLaan 和 @JimN 知道他们在说什么。 setOpaque(或更准确地说,isOpaque)是 Swing 引擎的渲染提示,可以帮助它优化其操作。检查javadocs,你就会明白我的意思。这与打开或关闭背景无关。嗯,这并不完全正确 - 默认情况下,JComponent 会巧妙地使用 opaque 属性来在适当的情况下自动绘制背景,但是如果如果你正在处理你自己的画,那么你的聪明才智可能会被推翻。

编辑:关于NoSuchMethodError。看看这个:

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) {
    ...
}

那干净多了。请注意,如果 1.7 版本成功,return 将使函数短路。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文