技术开发 频道

JDK 7探秘二:半透明和任意形状的窗口

  【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,如下所示:

GraphicsEnvironment ge;
ge
= GraphicsEnvironment.getLocalGraphicsEnvironment ();
if (!ge.getDefaultScreenDevice ().
        isWindowTranslucencySupported (GraphicsDevice.WindowTranslucency.TRANSLUCENT))
{
    System.err.println (
"simple translucency isn't supported");
    
return;
}

  我创建了一个STDemo程序演示简单半透明效果,使用滑块调节框架窗口的透明度,清单1显示了这个程序的源代码。

  清单1. STDemo.java

// 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所示。

 JDK 7探秘二:半透明和任意形状的窗口

图 1 窗口及其内容全部处于均匀透明的状态

0
相关文章