Java教程是针对JDK 8编写的。本页面描述的示例和实践不利用后续版本中引入的改进,并且可能使用已不再可用的技术。
有关Java SE 9及后续版本中更新的语言特性的摘要,请参阅Java语言更改。
有关所有JDK版本的新功能、增强功能以及已删除或已弃用选项的信息,请参阅JDK发布说明。
从Java平台标准版6(Java SE 6)更新10版本开始,您可以在Swing应用程序中添加半透明和形状窗口。本页面涵盖以下主题:
这个功能是JDK 7版本中公共AWT包的一部分,有以下三种形式:
点击启动按钮,使用Java™ Web Start运行GradientTranslucentWindowDemo示例。此示例需要JDK 7或更高版本。或者,要自己编译和运行示例,请参考示例索引。
Shape
对象的窗口。形状窗口可以是不透明的,也可以使用统一或逐像素的半透明性。以下屏幕截图显示了一个具有30%半透明性的椭圆形窗口。
UnsupportedOperationException
setShape
setOpacity
GraphicsDevice
isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency)
GraphicsDevice.WindowTranslucency
TRANSLUCENT
– 平台支持具有统一半透明度的窗口,每个像素具有相同的透明度值。PERPIXEL_TRANSLUCENT
– 平台支持具有像素级半透明度的窗口。这种能力是实现渐隐窗口的必要条件。PERPIXEL_TRANSPARENT
– 平台支持具有形状的窗口。GraphicsConfiguration
isTranslucencyCapable
PERPIXEL_TRANSLUCENT
GraphicsConfiguration
import static java.awt.GraphicsDevice.WindowTranslucency.*; // 确定默认的GraphicsDevice支持的能力。 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gd = ge.getDefaultScreenDevice(); boolean isUniformTranslucencySupported = gd.isWindowTranslucencySupported(TRANSLUCENT); boolean isPerPixelTranslucencySupported = gd.isWindowTranslucencySupported(PERPIXEL_TRANSLUCENT); boolean isShapedWindowSupported = gd.isWindowTranslucencySupported(PERPIXEL_TRANSPARENT);
IllegalComponentStateException
异常。
setOpacity(float)
Window
float
getOpacity
示例创建了一个透明度为55%(半透明度为45%)的窗口。如果底层平台不支持半透明窗口,则示例会退出。与透明度相关的代码以粗体显示。TranslucentWindowDemo.java
import java.awt.*; import javax.swing.*; import static java.awt.GraphicsDevice.WindowTranslucency.*; public class TranslucentWindowDemo extends JFrame { public TranslucentWindowDemo() { super("TranslucentWindow"); setLayout(new GridBagLayout()); setSize(300,200); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //添加一个示例按钮。 add(new JButton("我是一个按钮")); } public static void main(String[] args) { //确定GraphicsDevice是否支持半透明性。 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gd = ge.getDefaultScreenDevice(); //如果不支持半透明窗口,则退出。 if (!gd.isWindowTranslucencySupported(TRANSLUCENT)) { System.err.println( "不支持半透明性"); System.exit(0); } JFrame.setDefaultLookAndFeelDecorated(true); //在事件分派线程上创建GUI SwingUtilities.invokeLater(new Runnable() { @Override public void run() { TranslucentWindowDemo tw = new TranslucentWindowDemo(); //将窗口设置为55%的不透明度(45%的半透明度)。 tw.setOpacity(0.55f); //显示窗口。 tw.setVisible(true); } }); } }
请注意,按钮也受到均匀半透明性的影响。设置不透明度会影响整个窗口,包括窗口中包含的任何组件。
GradientPaint
在窗口上调用setBackground(new Color(0,0,0,0))
会导致软件使用alpha值来渲染像素级半透明性。实际上,调用setBackground(new Color(0,0,0,alpha)
,其中alpha
小于255,会安装像素级透明度。因此,如果调用setBackground(new Color(0,0,0,128))
并且不做其他操作,窗口将以每个背景像素50%的半透明度渲染。然而,如果您正在创建自己的alpha值范围,您可能希望使用alpha值为0。
尽管公共API没有禁止,但通常您会希望在无装饰窗口上启用每像素半透明性。在大多数情况下,使用装饰窗口的每像素半透明性是没有意义的。这样做可能会禁用装饰或引起其他平台相关的副作用。
要确定窗口是否使用每像素半透明性,可以使用isOpaque
方法。
以下是一个示例。首先,这里是实现示例所需的步骤:
setBackground(new Color(0,0,0,0))
。paintComponent
方法的JPanel
实例。paintComponent
方法中创建一个GradientPaint
实例。GradientPaint
类会平滑地插值矩形顶部到底部的alpha值。GradientPaint
实例设置为面板的绘制方法。以下是
示例的代码。如果底层平台不支持每像素半透明性,则该示例会退出。与创建渐变窗口相关的代码以粗体显示。GradientTranslucentWindowDemo.java
import java.awt.*; import javax.swing.*; import static java.awt.GraphicsDevice.WindowTranslucency.*; public class GradientTranslucentWindowDemo extends JFrame { public GradientTranslucentWindowDemo() { super("GradientTranslucentWindow"); setBackground(new Color(0,0,0,0)); setSize(new Dimension(300,200)); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel panel = new JPanel() { @Override protected void paintComponent(Graphics g) { if (g instanceof Graphics2D) { final int R = 240; final int G = 240; final int B = 240; Paint p = new GradientPaint(0.0f, 0.0f, new Color(R, G, B, 0), 0.0f, getHeight(), new Color(R, G, B, 255), true); Graphics2D g2d = (Graphics2D)g; g2d.setPaint(p); g2d.fillRect(0, 0, getWidth(), getHeight()); } } }; setContentPane(panel); setLayout(new GridBagLayout()); add(new JButton("我是一个按钮")); } public static void main(String[] args) { // 确定GraphicsDevice的支持情况。 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gd = ge.getDefaultScreenDevice(); boolean isPerPixelTranslucencySupported = gd.isWindowTranslucencySupported(PERPIXEL_TRANSLUCENT); //如果不支持透明窗口,退出。 if (!isPerPixelTranslucencySupported) { System.out.println( "不支持逐像素半透明"); System.exit(0); } JFrame.setDefaultLookAndFeelDecorated(true); // 在事件分派线程上创建GUI SwingUtilities.invokeLater(new Runnable() { @Override public void run() { GradientTranslucentWindowDemo gtw = new GradientTranslucentWindowDemo(); // 显示窗口。 gtw.setVisible(true); } }); } }
请注意,按钮不受逐像素半透明的影响。设置逐像素半透明只会影响背景像素。如果您想要窗口仅对背景像素产生均匀的半透明效果,可以调用setBackground(new Color(0,0,0,alpha))
,其中alpha
指定所需的半透明度。
setShape(Shape)
Window
Shape
设置窗口形状的最佳实践是在组件事件监听器的componentResized
方法中调用setShape
。这种做法将确保为窗口的实际大小正确计算形状。下面的示例使用了这种方法。
这个示例创建了一个椭圆形的窗口,透明度为70%。如果底层平台不支持窗口形状,示例会退出。如果底层平台不支持半透明,示例会使用标准的不透明窗口。你可以修改这个示例来创建一个同时使用逐像素半透明的窗口。
与窗口形状相关的代码以粗体显示。
import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.awt.geom.Ellipse2D; import static java.awt.GraphicsDevice.WindowTranslucency.*; public class ShapedWindowDemo extends JFrame { public ShapedWindowDemo() { super("ShapedWindow"); setLayout(new GridBagLayout()); // 最佳实践是在componentResized方法中设置窗口的形状。 // 这样,如果窗口大小发生变化,形状将被正确地重新计算。 addComponentListener(new ComponentAdapter() { // 给窗口设置椭圆形状。 // 如果窗口大小改变,形状将在此处重新计算。 @Override public void componentResized(ComponentEvent e) { setShape(new Ellipse2D.Double(0,0,getWidth(),getHeight())); } }); setUndecorated(true); setSize(300,200); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); add(new JButton("我是一个按钮")); } public static void main(String[] args) { // 确定GraphicsDevice可以支持什么。 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gd = ge.getDefaultScreenDevice(); final boolean isTranslucencySupported = gd.isWindowTranslucencySupported(TRANSLUCENT); // 如果不支持窗口形状,退出。 if (!gd.isWindowTranslucencySupported(PERPIXEL_TRANSPARENT)) { System.err.println("不支持窗口形状"); System.exit(0); } // 如果不支持半透明窗口,创建一个不透明窗口。 if (!isTranslucencySupported) { System.out.println( "不支持半透明窗口,创建一个不透明窗口"); } // 在事件分派线程上创建GUI SwingUtilities.invokeLater(new Runnable() { @Override public void run() { ShapedWindowDemo sw = new ShapedWindowDemo(); // 如果支持半透明,将窗口设置为70%透明度。 if (isTranslucencySupported) { sw.setOpacity(0.7f); } // 显示窗口。 sw.setVisible(true); } }); } }
com.sun.awt.AWTUtilities
Java SE 6 更新 10 中的方法 | JDK 7 的对应方法 |
---|---|
AWTUtilities.isTranslucencySupported(Translucency) |
GraphicsDevice.isWindowTranslucencySupported(WindowTranslucency) |
AWTUtilities.isTranslucencyCapable(GraphicsConfiguration) |
GraphicsConfiguration.isTranslucencyCapable() |
AWTUtilities.setWindowOpacity(Window, float) |
Window.setOpacity(float) |
AWTUtilities.setWindowShape(Window, Shape) |
Window.setShape(Shape) |
AWTUtilities.setWindowOpaque(boolean) |
Window.setBackground(Color) 将 new Color(0,0,0,alpha) 传递给此方法,其中 alpha 小于 255,可安装像素级半透明。 |