Documentation

The Java™ Tutorials
Hide TOC
How to Create Translucent and Shaped Windows如何创建半透明和成型的窗口
Trail: Creating a GUI With Swing
Lesson: Using Other Swing Features

How to Create Translucent and Shaped Windows如何创建半透明和塑形窗口

As of the Java Platform, Standard Edition 6 (Java SE 6) Update 10 release, you can add translucent and shaped windows to your Swing applications. 从Java Platform,Standard Edition 6(Java SE 6)Update 10发行版开始,您可以向Swing应用程序添加半透明和形状的窗口。This page covers the following topics:本页涵盖以下主题:

Supported Capabilities支持的功能

This functionality, which is part of the public AWT package in the JDK 7 release, takes three forms, as follows:此功能是JDK 7版本中公共AWT包的一部分,有三种形式,如下所示:

Determining a Platform's Capabilities确定平台的功能

Not all platforms support all of these capabilities. 并非所有平台都支持所有这些功能。An UnsupportedOperationException exception is thrown when code attempts to invoke the setShape or setOpacity methods on a platform that does not support these capabilities. 当代码尝试在不支持这些功能的平台上调用setShapesetOpacity方法时,将引发UnsupportedOperationException异常。Therefore, it is best practice to first check that the platform supports the capability that you want to implement. 因此,最佳做法是首先检查平台是否支持您想要实现的功能。The GraphicsDevice class provides the isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency) method that you can use for this purpose. GraphicsDevice类提供了可用于此目的的isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency)方法。You pass one of three enum values, defined in GraphicsDevice.WindowTranslucency, to this method:GraphicsDevice.WindowTranslucency中定义的三个枚举值之一传递给此方法: The GraphicsConfiguration class also provides the isTranslucencyCapable method to determine if PERPIXEL_TRANSLUCENT translucency is supported by the given GraphicsConfiguration object. GraphicsConfiguration类还提供isTranslucencyCapable方法,以确定给定的GraphicsConfiguration象是否支持PERPIXEL_TRANSLUCENT半透明。

Version note: The translucent and shaped window API was first added to the Java SE 6 Update 10 release as a private API. This functionality was moved to the public AWT package in the JDK 7 release. 这个半透明的成形窗口API最初作为一个私有API添加到JavaSE6Update10版本中。此功能已在JDK 7版本中转移到公共AWT包中。This tutorial describes the API that is available in the JDK 7 release. 本教程介绍JDK 7版本中可用的API。See Java SE 6 Update 10 API for a mapping of the private API in the Java SE 6 Update 10 release to the public API in the JDK 7 release. 有关Java SE 6 Update 10版本中的私有API到JDK 7版本中的公共API的映射,请参阅Java SE 6 Update 10 API
The following code shows how to check for all three capabilities:以下代码显示了如何检查所有三种功能:
import static java.awt.GraphicsDevice.WindowTranslucency.*;

// Determine what the default GraphicsDevice can support.
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);

Note: None of these capabilities work on windows in full-screen mode. 这些功能都不能在全屏模式下的窗口上工作。Invoking any of the relevant methods while in full-screen mode causes an IllegalComponentStateException exception to be thrown. 在全屏模式下调用任何相关方法都会引发IllegalComponentStateException异常。

How to Implement Uniform Translucency如何实现均匀半透明

You can create a window where each pixel has the same translucency by invoking the setOpacity(float) method in the Window class. 通过调用window类中的setOpacity(float)方法,可以创建一个窗口,其中每个像素都具有相同的半透明。The float argument passed to this method represents the translucency of the window and should be a value between 0 and 1, inclusive. 传递给此方法的float参数表示窗口的半透明性,应该是介于0和1之间的值,包括0和1。The smaller the number, the more transparent the window. 数字越小,窗口越透明。There is also a corresponding getOpacity method. 还有一个对应的getOpacity方法。

The TranslucentWindowDemo.java example creates a window that is 55 percent opaque (45 percent translucent). TranslucentWindowDemo.java示例创建了一个55%不透明(45%半透明)的窗口。If the underlying platform does not support translucent windows, the example exits. 如果底层平台不支持半透明窗口,则退出示例。The code relating to opacity is shown in bold.与不透明度相关的代码以粗体显示。

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 a sample button.
        add(new JButton("I am a Button"));
    }

    public static void main(String[] args) {
        // Determine if the GraphicsDevice supports translucency.
GraphicsEnvironment ge =
            GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gd = ge.getDefaultScreenDevice();

        //If translucent windows aren't supported, exit.
if (!gd.isWindowTranslucencySupported(TRANSLUCENT)) {
            System.err.println(
                "Translucency is not supported");
                System.exit(0);
        }
        
        JFrame.setDefaultLookAndFeelDecorated(true);

        // Create the GUI on the event-dispatching thread
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                TranslucentWindowDemo tw = new TranslucentWindowDemo();

                // Set the window to 55% opaque (45% translucent).
tw.setOpacity(0.55f);

                // Display the window.
                tw.setVisible(true);
            }
        });
    }
}

Note that the button is also affected by the uniform translucency. 请注意,按钮也受均匀半透明的影响。Setting the opacity affects the whole window, including any components that the window contains.设置不透明度会影响整个窗口,包括窗口包含的任何组件。

How to Implement Per-Pixel Translucency如何实现每像素半透明

Creating a window that uses per-pixel translucency involves defining alpha values over the rectangular area that the window occupies. 创建使用每像素半透明的窗口需要在窗口所占的矩形区域上定义alpha值。When a pixel's alpha value is zero, that pixel is fully transparent. 当像素的alpha值为零时,该像素是完全透明的。When a pixel's alpha value is 255, that pixel is fully opaque. 当像素的alpha值为255时,该像素完全不透明。When a pixel's alpha value is 128, that pixel is 50 percent translucent, and so on. 当一个像素的alpha值为128时,该像素是50%半透明的,依此类推。An easy way to create a smooth interpolation between alpha values is to use the GradientPaint class. 在alpha值之间创建平滑插值的一种简单方法是使用GradientPaint类。The included example uses this approach. 所包含的示例使用了这种方法。

Invoking setBackground(new Color(0,0,0,0)) on the window causes the software to use the alpha values to render per-pixel translucency. 在窗口上调用setBackground(new Color(0,0,0,0))会导致软件使用alpha值渲染每像素半透明。In fact, invoking setBackground(new Color(0,0,0,alpha), where alpha is less than 255, installs per-pixel transparency. 事实上,调用setBackground(new Color(0,0,0,alpha),其中alpha小于255,将安装每像素透明度。So, if you invoke setBackground(new Color(0,0,0,128)) and do nothing else, the window is rendered with 50 percent translucency for each background pixel. 因此,如果调用setBackground(new Color(0,0,0,128))而不执行其他操作,则窗口将以每个背景像素50%的半透明度渲染。However, if you are creating your own range of alpha values, you most likely will want an alpha value of 0.但是,如果您正在创建自己的alpha值范围,则很可能希望alpha的值为0。

While not prohibited by the public API, you will generally want to enable per-pixel translucency on undecorated windows. 虽然公共API不禁止,但您通常希望在未装饰的窗口上启用每像素半透明。In most cases, using per-pixel translucency on decorated windows does not make sense. 在大多数情况下,在装饰窗上使用每像素半透明是没有意义的。Doing so can disable the decorations, or cause other platform-dependent side effects.这样做可能会禁用装饰,或导致其他依赖于平台的副作用。

To determine if a window is using per-pixel translucency, you can use the isOpaque method.要确定窗口是否使用逐像素半透明,可以使用isOpaque方法。

An example follows. First, here are the steps required to implement the example:下面是一个例子。首先,以下是实施示例所需的步骤:

  1. Invoke setBackground(new Color(0,0,0,0)) on the window.在窗口上调用setBackground(new Color(0,0,0,0))
  2. Create a JPanel instance that overrides the paintComponent method.创建覆盖paintComponent方法的JPanel实例。
  3. In the paintComponent method, create a GradientPaint instance.paintComponent方法中,创建GradientPaint实例。
  4. In the example, the top of the rectangle has an alpha value of 0 (the most transparent) and the bottom has an alpha value of 255 (the most opaque). 在本例中,矩形的顶部的alpha值为0(最透明),底部的alphas值为255(最不透明)。The GradientPaint class smoothly interpolates the alpha values from the top to the bottom of the rectangle.GradientPaint类从矩形的顶部到底部平滑插值alpha值。
  5. Set the GradientPaint instance as the panel's paint method.GradientPaint实例设置为面板的绘制方法。

Here is the code for the GradientTranslucentWindowDemo.java example. 下面是GradientTranslucentWindowDemo.java示例的代码。If the underlying platform does not support per-pixel translucency, this example exits. 如果底层平台不支持每像素半透明,则退出此示例。The code specifically relating to creating the gradient window is shown in bold.与创建渐变窗口相关的代码以粗体显示。

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("I am a Button"));
    }

    public static void main(String[] args) {
        // Determine what the GraphicsDevice can support.
GraphicsEnvironment ge =
            GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gd = ge.getDefaultScreenDevice();
        boolean isPerPixelTranslucencySupported = 
            gd.isWindowTranslucencySupported(PERPIXEL_TRANSLUCENT);

        //If translucent windows aren't supported, exit.
if (!isPerPixelTranslucencySupported) {
            System.out.println(
                "Per-pixel translucency is not supported");
                System.exit(0);
        }

        JFrame.setDefaultLookAndFeelDecorated(true);

        // Create the GUI on the event-dispatching thread
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                GradientTranslucentWindowDemo gtw = new
                    GradientTranslucentWindowDemo();

                // Display the window.
                gtw.setVisible(true);
            }
        });
    }
}

Note that the button is not affected by the per-pixel translucency. 请注意,该按钮不受每像素半透明的影响。Setting the per-pixel translucency affects the background pixels only. 设置每像素半透明仅影响背景像素。If you want a window that has a uniformly translucent effect on the background pixels only, you can invoke setBackground(new Color(0,0,0,alpha)) where alpha specifies your desired translucency.如果希望窗口仅对背景像素具有均匀的半透明效果,可以调用setBackground(new Color(0,0,0,alpha)),其中alpha指定所需的半透明。

How to Implement a Shaped Window如何实现形状窗口

You can create a shaped window by invoking the setShape(Shape) method in the Window class. 您可以通过调用window类中的setShape(Shape)方法来创建一个有形状的窗口。The Shape argument that is passed to the method determines how the window is clipped. 传递给方法的Shape参数决定了窗口的剪裁方式。When a shape is set on a window, the window decorations are not re-formed to the new shape, so setting a shape works best on undecorated windows. 当在窗户上设置形状时,窗户装饰不会重新形成新的形状,因此设置形状最适合未装饰的窗户。

The best practice for setting the window's shape is to invoke setShape in the componentResized method of the component event listener. 设置窗口形状的最佳实践是在组件事件侦听器的componentResized方法中调用setShapeThis practice will ensure that the shape is correctly calculated for the actual size of the window. The following example uses this approach.这种做法将确保根据窗户的实际尺寸正确计算形状。以下示例使用此方法。

The ShapedWindowDemo.java example creates an oval-shaped window with 70 percent opacity. ShapedWindowDemo.java示例创建了一个不透明度为70%的椭圆形窗口。If the underlying platform does not support shaped windows, the example exits. 如果底层平台不支持成型窗口,则退出示例。If the underlying platform does not support translucency, the example uses a standard opaque window. 如果底层平台不支持半透明,则示例使用标准不透明窗口。You could modify this example to create a shaped window that also uses per-pixel translucency.您可以修改此示例以创建一个也使用逐像素半透明的成形窗口。

The code relating to shaping the window is shown in bold.与窗口形状相关的代码以粗体显示。

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());

        // It is best practice to set the window's shape in
        // the componentResized method.  Then, if the window
        // changes size, the shape will be correctly recalculated.
addComponentListener(new ComponentAdapter() {
            // Give the window an elliptical shape.
            // If the window is resized, the shape is recalculated here.
@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("I am a Button"));
    }

    public static void main(String[] args) {
        // Determine what the GraphicsDevice can support.
GraphicsEnvironment ge =
            GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gd = ge.getDefaultScreenDevice();
        final boolean isTranslucencySupported = 
            gd.isWindowTranslucencySupported(TRANSLUCENT);

        //If shaped windows aren't supported, exit.
if (!gd.isWindowTranslucencySupported(PERPIXEL_TRANSPARENT)) {
            System.err.println("Shaped windows are not supported");
            System.exit(0);
        }

        //If translucent windows aren't supported, 
        //create an opaque window.
        if (!isTranslucencySupported) {
            System.out.println(
                "Translucency is not supported, creating an opaque window");
        }

        // Create the GUI on the event-dispatching thread
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                ShapedWindowDemo sw = new ShapedWindowDemo();

                // Set the window to 70% translucency, if supported.
                if (isTranslucencySupported) {
                    sw.setOpacity(0.7f);
                }

                // Display the window.
                sw.setVisible(true);
            }
        });
    }
}

Java SE 6 Update 10 APIJava SE 6 Update 10 API

Changing the public API in an update release is not allowed, so when the translucent and shaped windows capability was added to the Java SE 6 Update 10 release, it was implemented in the private com.sun.awt.AWTUtilities class. 不允许在更新版本中更改公共API,因此当Java SE 6 update 10版本中添加半透明和成形窗口功能时,它是在私有com.sun.awt.AWTUtilities类中实现的。For the JDK 7 release, this functionality was moved to the public AWT package. The following table shows how the private methods map to the public methods. 对于JDK 7版本,此功能已转移到公共AWT包中。下表显示了私有方法如何映射到公共方法。
Method in Java SE 6 Update 10 JDK 7 Equivalent
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) Passing new Color(0,0,0,alpha) to this method, where alpha is less than 255, installs per-pixel translucency.new Color(0,0,0,alpha)传递给此方法,其中alpha小于255,将安装每像素半透明。

Previous page: How to Integrate with the Desktop Class
Next page: How to Decorate Components with the JLayer Class