半透明联合像素级透明和任意形状窗口
你可以联合像素级半透明(或简单半透明)和像素级透明实现一个半透明的任意形状窗口,我创建了一个CTSWDemo程序演示这是可能的,清单4中的代码扩展了前面的例子,包括了像素级半透明代码。
清单 4. CTSWDemo.java
// CTSWDemo.java
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class CTSWDemo extends JFrame
{
public CTSWDemo ()
{
super ("Combined Translucency with Per-Pixel Transparency and Shaped "+
"Window Demo");
setUndecorated (true); // Avoid decorated window artifacts.
JPanel gradPanel = new JPanel ()
{
Color colorA = new Color (255, 0, 0, 0);
Color colorB = new Color (255, 0, 0, 255);
protected void paintComponent (Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
GradientPaint gp;
gp = new GradientPaint (0.0f, 0.0f, colorA,
0.0f, getHeight (),
colorB, true);
g2d.setPaint (gp);
g2d.fillRect (0, 0, getWidth (),
getHeight ());
}
};
gradPanel.setPreferredSize (new Dimension (300, 200));
gradPanel.setLayout (new BoxLayout (gradPanel, BoxLayout.Y_AXIS));
JButton btnClose = new JButton ("Close");
ActionListener al;
al = new ActionListener ()
{
public void actionPerformed (ActionEvent ae)
{
System.exit (0);
}
};
btnClose.addActionListener (al);
btnClose.setAlignmentX (0.5f);
gradPanel.add (Box.createVerticalGlue ());
gradPanel.add (btnClose);
gradPanel.add (Box.createVerticalGlue ());
setContentPane (gradPanel);
if (!getGraphicsConfiguration ().isTranslucencyCapable ())
{
System.err.println ("per-pixel translucency not in effect for this "+
"graphics configuration");
System.exit (0);
}
setBackground (new Color (0, 0, 0, 0)); // Achieve per-pixel
// translucency.
pack ();
setShape (new Ellipse2D.Float (0, 0, getWidth (), getHeight ()));
setLocationRelativeTo (null);
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.
PERPIXEL_TRANSLUCENT))
{
System.err.println ("per-pixel translucency isn't "+
"supported");
return;
}
if (!ge.getDefaultScreenDevice ().
isWindowTranslucencySupported
(GraphicsDevice.WindowTranslucency.
PERPIXEL_TRANSPARENT))
{
System.err.println ("per-pixel transparency isn't "+
"supported");
return;
}
new CTSWDemo ();
}
};
EventQueue.invokeLater (r);
}
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class CTSWDemo extends JFrame
{
public CTSWDemo ()
{
super ("Combined Translucency with Per-Pixel Transparency and Shaped "+
"Window Demo");
setUndecorated (true); // Avoid decorated window artifacts.
JPanel gradPanel = new JPanel ()
{
Color colorA = new Color (255, 0, 0, 0);
Color colorB = new Color (255, 0, 0, 255);
protected void paintComponent (Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
GradientPaint gp;
gp = new GradientPaint (0.0f, 0.0f, colorA,
0.0f, getHeight (),
colorB, true);
g2d.setPaint (gp);
g2d.fillRect (0, 0, getWidth (),
getHeight ());
}
};
gradPanel.setPreferredSize (new Dimension (300, 200));
gradPanel.setLayout (new BoxLayout (gradPanel, BoxLayout.Y_AXIS));
JButton btnClose = new JButton ("Close");
ActionListener al;
al = new ActionListener ()
{
public void actionPerformed (ActionEvent ae)
{
System.exit (0);
}
};
btnClose.addActionListener (al);
btnClose.setAlignmentX (0.5f);
gradPanel.add (Box.createVerticalGlue ());
gradPanel.add (btnClose);
gradPanel.add (Box.createVerticalGlue ());
setContentPane (gradPanel);
if (!getGraphicsConfiguration ().isTranslucencyCapable ())
{
System.err.println ("per-pixel translucency not in effect for this "+
"graphics configuration");
System.exit (0);
}
setBackground (new Color (0, 0, 0, 0)); // Achieve per-pixel
// translucency.
pack ();
setShape (new Ellipse2D.Float (0, 0, getWidth (), getHeight ()));
setLocationRelativeTo (null);
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.
PERPIXEL_TRANSLUCENT))
{
System.err.println ("per-pixel translucency isn't "+
"supported");
return;
}
if (!ge.getDefaultScreenDevice ().
isWindowTranslucencySupported
(GraphicsDevice.WindowTranslucency.
PERPIXEL_TRANSPARENT))
{
System.err.println ("per-pixel transparency isn't "+
"supported");
return;
}
new CTSWDemo ();
}
};
EventQueue.invokeLater (r);
}
}
上面的梯度代码在创建Color对象时再次使用了alpha值,如图4所示,但半透明红色梯度现在只占用了椭圆形部分,而不是整个窗口。
图 4 setBackground()方法调用允许椭圆形内用红色半透明呈梯度渲染
小结
JDK 7对半透明和任意形状窗口的支持使得创建富有新意的UI更为容易,希望正式发布时会包含软剪裁或其它可移除边缘锯齿的技术。下一篇文章将会介绍JDK 7中新出现的JLayer Swing组件。