The Java Tutorials' Weblog
Translucent and Shaped Windows in JDK7
Here is another sneak peek at a page that was just completed for the JDK7 update of the Swing tutorial.Let us know what you think.
-- Sharon Zakhour
How to Create Translucent and Shaped Windows
As of the Java SE 6 update 10 (6u10) release, you can add translucent and shaped windows to your Swing applications. This functionality, part of the public AWT package in JDK 7, takes three forms:- You can create a window with uniform translucency, where each
pixel has the same translucency (or alpha) value.
The following screen shot shows a window with 45% translucency:

- You can create a window with per-pixel translucency,
where each pixel has its own alpha value. With this feature you can,
for example, create a window that fades away to nothing by defining a gradient
in the alpha values. The following screenshot shows a
window with gradient translucency from the top
(fully translucent) to the bottom (fully opaque):

- You can create a window with any
Shapethat you can define. Shaped windows can be opaque, or can use uniform, or per-pixel translucency. The following screen shot shows an oval-shaped window with 30% translucency:
- Determining a Platform's Capabilities
- How to Implement Uniform Translucency
- How to Implement Per-Pixel Translucency
- How to Implement a Shaped Window
- JavaSE Release 6 Update 10 API
- For More Information
Determining a Platform's Capabilities
Not all platforms support all of these capabilities. AnUnsupportedOperationException exception is thrown when
code attempts to invoke setShape or setOpacity
on a platform that does not support these features.
Therefore, it is best practice to first check
that the platform supports the capability you want to implement.
The GraphicsDevice class provides the
isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency) method that you can use for this purpose. You pass one of three enum
values, defined in
GraphicsDevice.WindowTranslucency, to this method:
TRANSLUCENT– The underlying platform supports windows with uniform translucency, where each pixel has the same alpha value.PERPIXEL_TRANSLUCENT– The underlying platform supports windows with per-pixel translucency. This capability is required to implement windows that fade away.PERPIXEL_TRANSPARENT– The underlying platform supports shaped windows.
GraphicsConfiguration class also provides the
isTranslucencyCapable method to determine if PERPIXEL_TRANSLUCENT
translucency is supported by the given GraphicsConfiguration
object.
The following code shows how to check for all three capabilities:
Version note: Translucent and shaped window API was first added to the JavaSE 6 update 10 release as a private API. This functionality was moved to the public AWT package in the JDK 7 release. This tutorial describes the API available in the JDK 7 release. See JavaSE Release 6 update 10 API for a mapping of the private API in 6u10 to the public API in the JDK 7 release.
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 anIllegalComponentStateExceptionexception to be thrown.
How to Implement Uniform Translucency
You can easily create a window where each pixel has the same translucency by invoking thesetOpacity(float) method in the Window class. The float
argument passed to this method should be between 0 and 1, inclusive,
and represents the translucency of the window. The smaller the number,
the more transparent the window. There is also a corresponding
getOpacity method.
The following example creates a window that is 55% opaque (45% translucent). 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 TranslucentWindow extends JFrame {
public TranslucentWindow() {
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);
}
// Create the GUI on the event-dispatching thread
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
TranslucentWindow tw = new TranslucentWindow();
// 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. When a pixel's alpha is zero, that pixel is fully transparent. When a pixel's alpha is 255, that pixel is fully opaque. When a pixel's alpha is 128, that pixel is 50% translucent, and so on. An easy way to create a smooth interpolation between alpha values is to use theGradientPaint class. 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. In fact, invoking
setBackground(new Color(0,0,0,alpha), where alpha
is less than 255, installs per-pixel transparency. So, if you
invoke setBackground(new Color(0,0,0,128)) and do nothing else,
the window is rendered with 50% translucency for each background pixel.
However, if you are creating your own range of alpha values,
you most likely will want an alpha value of 0.
While not prohibited by the public API, you will generally want to enable per-pixel translucency on undecorated windows. In most cases, using per-pixel translucency on decorated windows does not make sense, and 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.
An example is included below. The steps required to implement the example are as follows:
- Invoke
setBackground(new Color(0,0,0,0))on the window. - Create a
JPanelinstance that overrides thepaintComponentmethod. - In the
paintComponentmethod, create aGradientPaintinstance. In the included example, the top of the rectangle has an alpha of 0 (the most transparent) and the bottom has an alpha of 255 (the most opaque). TheGradientPaintclass smoothly interpolates the alpha values from the top to the bottom of the rectangle. - Set the
GradientPaintinstance as the panel's paint method.
Here is the code for the GradientWindow example.
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 GradientTranslucentWindow extends JFrame {
public GradientTranslucentWindow() {
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() {
GradientTranslucentWindow gtw = new GradientTranslucentWindow();
// 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.
How to Implement a Shaped Window
You can easily create a shaped window by invoking thesetShape(Shape) method in the Window class. The Shape
passed to the method determines how the window is clipped.
When setting a shape on a window, the window
decorations are not re-formed to the new shape,
so it 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. This will ensure that the
shape is correctly calculated for the actual size of the window.
The included example uses this approach.
The following example creates an oval-shaped window with 70% translucency. If the underlying platform does not support shaped windows, the example exits. If the underlying platform does not support translucency, the example uses an 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 ShapedWindow extends JFrame {
public ShapedWindow() {
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() {
ShapedWindow sw = new ShapedWindow();
// Set the window to 70% translucency, if supported.
if (isTranslucencySupported) {
sw.setOpacity(0.7f);
}
// Display the window.
sw.setVisible(true);
}
});
}
}
JavaSE Release 6 Update 10 API
Changing public API in an update release is not allowed, so when the translucent and shaped windows capability was added to the JavaSE 6u10 release, it was implemented in the privatecom.sun.awt.AWTUtilities class. For the JDK7 release,
this functionality was moved to the public AWT package.
The following table shows how the private methods map to the
public methods.
| Method in JavaSE 6u10 | 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.
|
For More Information
- The How to Create Translucent and Shaped Windows article. This article describes 6u10 API.
- The Translucent and Shaped Swing Windows article. This article describes 6u10 API.
- Romain Guy's Curious Creature blog entry shows a demo with a nice application of a a translucent shaped window.
Posted at 01:08PM Aug 13, 2009 by The Java Tutorial Team | Comments[3]
Thursday Aug 13, 2009
A very nice posting for all who considers java API a weak library.This is definately an extreme engineering which shows how powerfull java is.How easy it is to build such professinal GUI with java.
I really appreciate your work.Hope you will keep writing.
Posted by Manish Kumar Thakur on August 27, 2009 at 08:17 AM PDT #
Nice article! A very clear and concise instruction on how to use the feature.
Posted by Dmitry Bondarenko on August 28, 2009 at 07:26 AM PDT #
Thanks, Manish and Dmitry. Nice to hear from you, Dmitry. :)
Posted by Sharon Zakhour on September 17, 2009 at 09:12 AM PDT #