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%半透明性的椭圆形窗口。
UnsupportedOperationExceptionsetShapesetOpacityGraphicsDeviceisWindowTranslucencySupported(GraphicsDevice.WindowTranslucency)GraphicsDevice.WindowTranslucency
TRANSLUCENT – 平台支持具有统一半透明度的窗口,每个像素具有相同的透明度值。PERPIXEL_TRANSLUCENT – 平台支持具有像素级半透明度的窗口。这种能力是实现渐隐窗口的必要条件。PERPIXEL_TRANSPARENT – 平台支持具有形状的窗口。GraphicsConfigurationisTranslucencyCapablePERPIXEL_TRANSLUCENTGraphicsConfiguration
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)WindowfloatgetOpacity
示例创建了一个透明度为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)WindowShape
设置窗口形状的最佳实践是在组件事件监听器的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,可安装像素级半透明。 |