213
Chapter 6
C H A P T E R S I X
Transparent and Animated
Windows
Hacks 41–47
In the previous chapter, our window hacks generally played by the rules—
we simulated the earthquake dialog
[Hack #38] by animating calls to
setLocation( ), and switched to a mini-size window [Hack #40] by calling
setSize( ) and removing some window decorations.
This chapter’s hacks approach from outside the Window API per se, by
hacking the windows with Java 2D, stuffing things into the glass pane of a
JDialog or JFrame, and more. Some of them are practical, some are just
pretty, but all of these hacks offer something unexpected.
H A C K
#41
Transparent Windows Hack #41
Create translucent and shaped windows, while avoiding native code, with
clever use of a screenshot.
One of the most commonly requested Swing features is transparent win-
dows. Also called shaped windows, these are windows that have transparent
portions, allowing the desktop background and other programs to shine
through. Java doesn’t provide any way of creating transparent windows
without using the Java Native Interface (JNI) (and even then the native plat-
form must support transparency as well), but that’s not going to stop us. We
can cheat using one of my favorite techniques, the screenshot.
The process of faking a transparent window is basically:
1. Take a screenshot before the window is shown.
2. Use that screenshot as the background of the window.
3. Adjust the position so that the screenshot and the real screen line up,
creating the illusion of transparency.
This is the easy part. The hard part is updating the screenshot when the win-
dow moves or changes.
214
|
Chapter 6, Transparent and Animated Windows
#41 Transparent Windows
HACK
To start off, create a JPanel subclass that can capture the screen and paint it
as the background, as shown in Example 6-1.
First, the constructor saves a reference to the parent
JFrame; then it calls
updateBackground( ), which captures the entire screen using java.awt.Robot.
createScreenCapture( )
, and saves the capture in the background variable.
paintComponent( ) gets the panel’s absolute position on screen and then fills
the panel with the background image, shifted to account for the panel’s
location. This makes the fake background image line up with the real back-
ground, giving the appearance of transparency.
You can run this with a simple
main( ) method, dropping a few components
onto the panel and putting it into a frame:
public static void main(String[] args) {
JFrame frame = new JFrame("Transparent Window");
TransparentBackground bg = new TransparentBackground(frame);
bg.setLayout(new BorderLayout( ));
JButton button = new JButton("This is a button");
bg.add("North",button);
Example 6-1. A transparent background component
public class TransparentBackground extends Jcomponent {
private JFrame frame;
private Image background;
public TransparentBackground(JFrame frame) {
this.frame = frame;
updateBackground( );
}
public void updateBackground( ) {
try {
Robot rbt = new Robot( );
Toolkit tk = Toolkit.getDefaultToolkit( );
Dimension dim = tk.getScreenSize( );
background = rbt.createScreenCapture(
new Rectangle(0,0,(int)dim.getWidth( ),
(int)dim.getHeight( )));
} catch (Exception ex) {
p(ex.toString( ));
ex.printStackTrace( );
}
}
public void paintComponent(Graphics g) {
Point pos = this.getLocationOnScreen( );
Point offset = new Point(-pos.x,-pos.y);
g.drawImage(background,offset.x,offset.y,null);
}
}
Transparent Windows #41
Chapter 6, Transparent and Animated Windows
|
215
HACK
JLabel label = new JLabel("This is a label");
bg.add("South",label);
frame.getContentPane( ).add("Center",bg);
frame.pack( );
frame.setSize(150,100);
frame.show( );
}
The code produces a window that looks like Figure 6-1.
The code is pretty simple, but it has two big flaws. First, if the window is
moved, the background won’t be refreshed automatically.
paintComponent( )
only gets called when the user resizes the window. Second, if the screen ever
changes, it won’t match up with the background anymore.
You really don’t want to update the screenshot often, though, because that
involves hiding the window, taking a new screenshot, and then reshowing
the window—all of which is disconcerting to the user. Actually detecting
when the rest of the desktop changes is almost impossible, but most changes
happen when the foreground window changes focus or moves. If you accept
this idea (and I do), then you can watch for those events and only update the
screenshot when that happens:
public class TransparentBackground extends JComponent
implements ComponentListener, WindowFocusListener,
Runnable {
private JFrame frame;
private Image background;
private long lastupdate = 0;
public boolean refreshRequested = true;
Figure 6-1. Transparent windows in action

Get Swing Hacks now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.