【IT168 文档】从Java SE 6u10(Build 12)开始,Java引入了com.sun.awt.AWTUtilities类提供半透明和任意形状窗口的支持,这个是个临时类,因为6u10不是一个Java SE主版本,没有提供抽象窗口工具集API(Abstract Window Toolkit API,AWT API),也没有修改现有API。在JDK 7中,AWTUtilities类将不复存在,AWT类也做了许多改变,以更好地支持半透明和任意形状的窗口,本文将为大家介绍一下JDK 7中提供的3种半透明窗口,另外也会涉及到任意形状窗口的介绍。
简单的半透明窗口
简单的半透明窗口就是透明度均匀分布的窗口,所有像素的不透明度值都一样,这个值越小,窗口越透明,达到最小值时,窗口就是完全透明的了,相反,如果值越大则越不透明。
JDK 7给java.awt.Window类增加了public void setOpacity(float opacity)和public float getOpacity()两个方法来实现简单的半透明窗口效果,前一个方法需要一个不透明度参数,其取值范围是0.0(完全透明)-1.0(完全不透明)。
在窗口上调用setOpacity()方法激活其简单半透明效果,注意指定的参数值不能小于0.0,也不能大于1.0,否则setOpacity()会抛出一个IllegalArgumentException异常。
如果窗口处于全屏模式且不透明度值小于1.0,setOpacity()方法会抛出一个java.awt.IllegalComponentStateException异常,如果不支持简单透明度且不透明度值小于1.0,它会抛出UnsupportedOperationException异常。
java.awt.GraphicsDevice类提供了一个public Window getFullScreenWindow()方法确定窗口是否处于全屏模式,这个类也提供了一个public boolean isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency translucencyKind)方法确定当前的显示设备是否支持简单透明效果,如果显示设备支持这个方法参数指定的半透明效果,isWindowTranslucencySupported()就返回True,对于简单半透明效果,这个方法的参数必须是GraphicsDevice.WindowTranslucency.TRANSLUCENT,如下所示:
ge = GraphicsEnvironment.getLocalGraphicsEnvironment ();
if (!ge.getDefaultScreenDevice ().
isWindowTranslucencySupported (GraphicsDevice.WindowTranslucency.TRANSLUCENT))
{
System.err.println ("simple translucency isn't supported");
return;
}
我创建了一个STDemo程序演示简单半透明效果,使用滑块调节框架窗口的透明度,清单1显示了这个程序的源代码。
清单1. STDemo.java
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class STDemo extends JFrame
{
public STDemo ()
{
super ("Simple Translucency Demo");
setDefaultCloseOperation (EXIT_ON_CLOSE);
final JSlider slider = new JSlider (0, 100, 100);
ChangeListener cl;
cl = new ChangeListener ()
{
public void stateChanged (ChangeEvent ce)
{
JSlider source = (JSlider) ce.getSource ();
STDemo.this.setOpacity (source.getValue ()/100.0f);
}
};
slider.addChangeListener (cl);
getContentPane ().setLayout (new FlowLayout ());
getContentPane ().add (new JLabel ("TRANSP"));
getContentPane ().add (new JPanel () {{ add (slider); }});
getContentPane ().add (new JLabel ("OPAQUE"));
getRootPane ().setDoubleBuffered (false);
pack ();
setVisible (true);
}
public static void main (String [] args)
{
Runnable r;
r = new Runnable ()
{
public void run ()
{
GraphicsEnvironment ge;
ge = GraphicsEnvironment.getLocalGraphicsEnvironment ();
if (!ge.getDefaultScreenDevice ().
isWindowTranslucencySupported
(GraphicsDevice.WindowTranslucency.
TRANSLUCENT))
{
System.err.println ("simple translucency isn't "+
"supported");
return;
}
new STDemo ();
}
};
EventQueue.invokeLater (r);
}
}
上面的代码创建了一个滑块,为该组件注册了一个变化监听器,当滑块组件移动时,这个组件触发变化事件,监听器调用setOpacity(),参数就使用滑块的当前值。
上面的代码使用new JPanel () {{ add (slider); }}创建了一个Swing面板,并在面板上添加了一个滑块组件,从本质上讲,这个快捷方式是先实例化JPanel的一个子类,然后用这个子类的实例初始化滑块组件。
Swing组件的双倍缓存可以制造出意想不到的视觉效果,当你拖动滑块使窗口完全透明时,你将只能看到滑块本身,但清单1中的代码通过getRootPane ().setDoubleBuffered (false);禁用了双倍缓存。
编译并运行STDemo,移动滑块就能看到简单半透明窗口效果了,如图1所示。
图 1 窗口及其内容全部处于均匀透明的状态