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

如何在Java中使轻量级Swing或AWT组件透明,java,swing,awt,transparency,Java,Swing,Awt,Transparency,不久前,我尝试为Swing/AWT组件实现一种半透明方法,现在我第一次尝试了它。但是,在实现时,UI中会出现一些小故障。方法代码如下: public static void setTransparency(Component comp, float t) { try { if (comp instanceof Window) { try { //For JDK 1.7 ((Window) comp

不久前,我尝试为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%可靠的,如上所示。

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

Graphics2D g2 = (Graphics2D) comp.getGraphics().create();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, t));
comp.paint(g2);
g2.dispose();
只能在调用
绘制(图形g)
的过程中绘制组件。在调用
setTransparency
方法期间进行绘制是个坏主意,因为它将在Swing下次决定调用
paint
时被擦除。您需要使组件在
paintComponent
方法中处理自己的透明度

还有:
if(!th.getClass().isInstance(新的NoSuchMethodError())

你到底在干什么?简单的
捕获(NoSuchMethodError e)
有什么问题?或者,如果您确实想使用instanceof,那么
th instanceof NoSuchMethodError

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

编辑:关于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) {
    ...
}
void setTransparency(窗口w,双t){
试一试{
设置透明度17(w,t);
返回;
}
捕获(无此错误){
System.err.println(“JRE*小于1.7!”);//我们知道JRE必须小于1.7,因为1.7中存在正确的方法。
}
捕获(可丢弃的t){
t、 printStackTrace();
}
试一试{
设置透明度16(w,t);
}
捕获(可丢弃的t){
System.err.println(“Boom!”);
}
}
无效设置透明度17(窗口w,双t){
...
}
无效设置透明度16(窗口w,双t){
...
}

那要干净得多。请注意,如果1.7版本成功,返回的
将使函数短路。

啊,您可能想看看JLayer(或JXLayer for
请参见

设置窗口半透明或组件时是否会发生这种情况?用什么JDK版本?@prunge正如我在最后一句中所说的,它只是组件。窗口半透明效果很好。我正在JDK1.7_1和JDK1.6_29上测试,您不是在寻找JComponent#setOpaque(false)吗?你发布的代码毫无意义(试图将其透明化一次不会持久)@WalterLaan你知道
JComponent#setOpaque(布尔b)
的作用吗?那不是我想要的。我想要整个组件的半透明度,而不是背景的开/关。如果背景的任何部分必须显示给组件,那么组件必须将“不透明”设置为false。是的,这就是你想要的。答:我认为我不能静态地更改任何任意组件的
paint
方法。如果可以,请告诉我怎么做。B:首先,一个
NoSuchMethodError
不是“简单的”,我抓住它是因为
Window#setOpacity(float f)
在小于7的JRE中不存在,所以我不必打印堆栈,因为我知道发生了什么,下一个要运行的代码将适用于JRE 6。u C:我检查了Javadocs,我承认你的智慧。然而,我认为他们的意思是,将其设置为非不透明是整个过程solution@Supuhstar:所以您不控制要使其半透明的组件?我认为这是你自己的组件,你试图使半透明。在任何情况下,您都可以将想要半透明的每个组件包装在另一个了解半透明的组件中,并在其中使用alpha混合。@Supuhstar:NoSuchMethodError有什么不简单的<代码>尝试{dosomething17 specific();}catch(NoSuchMethodError e){dosomething16 specific();}
应该能帮你解决这个问题。不简单的不是处理,而是导致它发生的原因。与
Error
的所有扩展一样,
NoSuchMethodError
意味着编译后的代码与现有库不匹配,无法执行。这并不像
索引自动边界异常那样简单,我的观点是,您仍然可以通过简单的
捕获(NoSuchMethodError)
来捕获它,而不是使用精心设计的(缓慢的)
getClass().isInstance(新的NoSuchMethodError())
。你在抓住它之后实际上做了什么是一个完全不同的问题。那太好了,我可能最终会使用类似的东西。然而,它并没有回答我的问题。