Per-Pixel Translucency
Per-pixel translucency lets you control the opacity of each window pixel, resulting in parts of a window being more translucent than other parts. (Per-pixel translucency can be used to make a window evenly translucent, but it consumes more resources than simple translucency.)
JDK 7 supports per-pixel translucency by modifying Window's public void setBackground(Color bgColor) method to detect its argument's alpha component. If alpha isn't 1.0 (window is opaque), the alpha of each pixel drawn on the window will be respected.
This method throws IllegalComponentStateException if the window is in full-screen mode and the background color's alpha is less than 1.0, and UnsupportedOperationException if per-pixel translucency isn't supported and alpha is less than 1.0.
To avoid the latter exception, call GraphicsDevice's isWindowTranslucencySupported() method with argument GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT, and check the return value, as follows:
GraphicsEnvironment ge; ge = GraphicsEnvironment.getLocalGraphicsEnvironment (); if (!ge.getDefaultScreenDevice (). isWindowTranslucencySupported (GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT)) { System.err.println ("per-pixel translucency isn't supported"); return; }
It's also necessary to determine whether the window itself supports per-pixel translucency. Accomplish this task by invoking java.awt.GraphicsConfiguration's public Boolean isTranslucencyCapable() method, which returns true if this is the case:
// The following code fragment continues from the previous code fragment, but assumes that // the current class is a descendent of java.awt.Window. if (!getGraphicsConfiguration ().isTranslucencyCapable ()) { System.err.println ("per-pixel translucency not in effect for this graphics configuration"); System.exit (0); }
If you want to determine the current background color alpha value, invoke Window's public Color getBackground() method. Also, you can invoke the new public boolean isOpaque() method to find out if the window is opaque (true returns).
I've created a PPTDemo application that demonstrates per-pixel translucency (see Listing 2). Because the window is undecorated, you'll need to click its (horizontally and vertically centered) close button to terminate the application.
Listing 2PPTDemo.java
// PPTDemo.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.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class PPTDemo extends JFrame { public PPTDemo () { super ("Per-Pixel Translucency Demo"); JPanel gradPanel = new JPanel () { // Transparent red Color colorA = new Color (255, 0, 0, 0); // Solid red 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 (); 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; } new PPTDemo (); } }; EventQueue.invokeLater (r); } }
Listing 2 presents a JPanel subclass that creates a pair of java.awt.Color objects with transparent (0) and opaque (255) alpha values. Its paintComponent() method works with java.awt.GradientPaint to paint a gradient of alpha values across the panel's surface.
Later on, Listing 2 installs this panel as the frame window's content pane, verifies that the window's graphics configuration supports per-pixel translucency, undecorates the window, and invokes setBackground() to enable the per-pixel translucent window.
After packing the panel to its preferred size, Listing 2 invokes setLocationRelativeTo(null) to center the panel on the screen. Following setVisible(true), the translucent panel appears: transparent at the top, opaque at the bottom, and translucent in-between. See Figure 2.
Figure 2 The translucency decreases as the gradient moves toward the bottom of the window. The button remains opaque.