Translucent and shaped windows in core Java
I first spotted it about a month ago, and today’s build 12 of JDK 6.0u10 delivers on the promise – translucent and shaped windows with core Java classes only!
So, what do you do? First, head over to the JDK6 space at java.net and install 6u10 build 12. After that, you need to point to that install from your project (either IDE or a build script). As Richard mentioned in his Javaposse’s spot, Sun couldn’t publish the relevant APIs in a java.* or javax.* package since officially 6u10 is still not considered a major release. So, the APIs are in com.sun.awt.AWTUtilities. Of course, this may change its place (like Nimbus did), but you can at least start exploring it.
There are a few public static methods in this class, and since the signatures are self-explanatory, you don’t really need the source code. For starters, the inner Translucency enum has three values:
- PERPIXEL_TRANSPARENT – ability to create a shaped window
- TRANSLUCENT – ability to create a translucent window
- PERPIXEL_TRANSLUCENT – ability to create a translucent shaped window
To test support for a specific translucency mode, use AWTUtilities.isTranslucencySupported(Translucency) API. To test whether the specific GraphicsConfiguration supports translucency, use AWTUtilities.isTranslucencyCapable(GraphicsConfiguration) API. This Java class is a simple test utility that illustrates the usage of these two methods. Best thing – even on my Windows 2003 server machine these APIs return true!
Once you know that a specific translucency mode is supported, it’s time to create a shaped and / or translucent window. Let’s start with a simple frame with a few controls (Simple window – java class). Here is how it looks like, with a button, a check box, a radio button and a progress bar:
![]()
Let’s make it shaped (Shaped window – java class). For this, we use AWTUtilities.setWindowShape(Window, Shape). It’s hard to say without seeing the code, but the window has to be undecorated – call JFrame.setDefaultLookAndFeelDecorated(true). Otherwise the window is shown in usual rectangular shape. It would be nice to have a boolean return value that indicates a success of the operation. Here is how our window looks now:
![]()
Let’s make a translucent window (Translucent window – Java class). For this, we use AWTUtilities.setWindowOpacityWindow, float). As you can see, the translucency factor is global, and (at least for now) you can not control translucency of each pixel. Here is how our window looks like with 50% opacity:
![]()
And you can combine both calls to have a translucent and shaped window (Translucent shaped window – Java class):
![]()
There are a few other additional public methods in AWTUtilities:
- getWindowOpacity(Window)
- getWindowShape(Window)
- setWindowOpaque(Window, boolean)
- isWindowOpaque(Window)
I think that the only two things that i’m missing is the per-pixel translucency support and soft-clipping of shaped windows (this would depend on the first item).
Congratulations to the AWT team for making this happen!
Related posts:
- Translucent and shaped windows in JDK 7 The latest weekly drop of JDK 7 (b57) has finally exposed the functionality of translucent...
- More tricks with translucent Swing windows The java.net site has just published my article on translucent and shaped windows, and it...
- Soft clipping and per-pixel translucency for Swing windows The entry on translucent and shaped windows in Swing has generated quite a lot of...
- Colorizing Swing components under core look-and-feels Last week i talked about using Substance decoration painters to visually offset Flamingo ribbon component....
February 27th, 2008 at 10:08 am
Yay! we were waiting for this one since the early days of the XMMS player (a really loong time ago)
February 27th, 2008 at 10:47 am
Being a long-time java developer on the Mac, I just assumed you got translucency by setting the frame background color to something with like new Color(1f,1f,1f,0.5f)
Didn’t realise you couldn’t do that in Windows/Linux.
February 27th, 2008 at 10:57 am
Adrian,
It never worked on Windows / Linux. Up until now the JNA project has been the only publicly available free solution (as far as i know).
February 27th, 2008 at 12:03 pm
Excellent news.
February 27th, 2008 at 1:34 pm
I haven’t looked at the exact API, but I hope it is not limited to Windows and allows setting alpha and shapes to any AWT component.
This feature is useful to shape native embedded components (I currently have to use a modified version of some JNA example to do that).
February 27th, 2008 at 11:45 pm
Actually the setWindowOpaque(window, false) method turns on the per-pixel translucency mode. In this mode the background of the frame is not visible on the screen. However, any component (JPanle, JButton, whatever) added to the window is visible. And of course you can override the paintComponent() method of your panel or button to fill it with pixels having arbitrary alpha-component of their colors.
So, have fun! :)
February 27th, 2008 at 11:56 pm
Anthony – thanks for the clarifications. Have you considered JNA’s approach where you install a BufferedImage as the translucency mask. Alpha value of the pixel in that image defines the window translucency. Wouldn’t that be simpler to use, especially on complex UIs?
In addition, calling setWindowShape is good as long as you don’t resize the window. Of course, one would have to register a listener and update the shape. The question is – how expensive is this call? I did see some noticeable lag introduced by this new functionality the first time the window is shown (until it becomes responsive).
Thanks
Kirill
February 28th, 2008 at 12:15 am
Kirill, we investigated the JNA’s implementation of the effects. AFAIR, it does not *install* any BufferedImage, it simply paints the whole frame into the BufferedImage, and then passes the image to the MS Windows API function. And we use quite a similar approach, so I guess that using the AWT’s implementation is pretty much the same simple thing as using the JNA’s one.
Regarding the setWindowShape(), I would recommend invoking it from whithin the componentResized() method of the ComponentListener installed on the frame. This way you will always have the correct shape of your window, and this should not cause any significant performance degradations as well. The first call always takes a bit longer because we need to check whether it’s supported and do a couple of other initialization-related stuff. But the subsequent calls should execute faster.
February 28th, 2008 at 12:29 am
This is excellent news !
The most interesting feature for me is transparency based on the alpha value of the pixel. This would allow vista-like windows, shadows etc … (see
http://swing-fx.blogspot.com/2008/02/per-pixels-transparency-with-jframe.html, sorry for advertising :) )
Also how expensive is it to turn on transparency with setWindowOpaque(window, false) ?
February 28th, 2008 at 2:49 am
Ah that’s where they hid the API, I noticed the bug fix report but couldn’t find where the API was kept to try it out.
Unfortunately TRANSLUCENT windows are not supported on my linux box (so no drop shadows or antialiasing) :(, though shaped windows are but with some pretty major bugs in them (resizing from the left or top edges causes a lot of problems), moving the window around is fine. I’m looking forward to using this api in some of my apps, roll on shaped preview/zoom windows :)
February 28th, 2008 at 2:57 am
Sorry, the resizing bug is present even without the translucency enabled, must be a bug in the LnF decoration under Metal.
February 28th, 2008 at 4:01 am
I really wish they would first fix the font rendering problems, such as making a font’s thickness increase proportionally with its size, rather than suddenly getting thicker at a few certain sizes. At least they’re hacking a DPI fix for Swing with Nimbus, we’ll see how long we have to wait for the native L&Fs.
February 28th, 2008 at 6:57 am
Are L&F decorated windows still screwed up? It seems a bit pointless adding fancy doodads if the basics don’t work right.
February 28th, 2008 at 8:00 am
Matt, as Anthony pointed out, you need to update the shape in componentResized() event. Otherwise the shape no longer matches the current size of the window.
February 28th, 2008 at 10:10 am
This is a great news!
February 28th, 2008 at 10:17 am
A note regarding how expensive it is to turn on these effects. On XP
turning on transparency or translucency (not shaping) will disable
hw acceleration for the particular window since GDI calls used to
implement these features don’t work well with hw acceleration.
Microsoft fixed this in Vista, so it should work fine and accelerated there.
Lukasz:
> I really wish they would first fix the font rendering problems,
http://forums.java.net/jive/thread.jspa?threadID=37260&tstart=0
Done.
Dmitri
February 28th, 2008 at 12:56 pm
kirill, i’m wondering whether the native font rendering fixes make the bramble plugin for substance unneeded now ? (i guess that would be the next blog entry :)
February 28th, 2008 at 1:00 pm
lqd – the native font rasterization in 6u10 b12 has not (yet) been backported to JDK 5.0 or a stable 6.0 release. So, the Bramble plugin still has a use case.
Thanks
Kirill
February 28th, 2008 at 8:39 pm
Great news … I guess to use this you just have to be careful not to break code that uses older 1.6 versions. Methods like this make me wish there was a scripting option you could use (perhaps there is) to enable without having to resort to reflection tricks.
ex:
JFrame f = new JFrame(“Test);
Script.execute(“com.sun.awt.AWTUtilities.setWindowOpacity($1, 0.5f);”, f);
February 29th, 2008 at 1:29 am
Kirill, that is what I was doing :).
After a quick search in the bug database the problem I’m seeing is probably this one:
http://bugs.sun.com/view_bug.do?bug_id=4649181
and this happens under default conditions with Matal window decorations enabled so isn’t really related to this blog or transparency, unless you want to resize your window that is ;)
March 1st, 2008 at 5:28 pm
Dmitri Trembovetski, after a quick test on Windows XP with 1.5 gb RAM, I was able to confirm that it is very expensive to use translucent windows on XP. Memory use shoots up very dramatically under tests with NetBeans’ profiler. I am looking forward to trying it on Vista. Thanks for your clarification.
March 2nd, 2008 at 12:42 pm
I tried the method “setWindowsOpaque(window,false), but there seams to be the following bug: if i override the paint method of JWindow, the background of the JWindow is invisible. So I can paint a shape over the windows desktop, for example. But when I call the repaint method, my painting doesn’t repaint as I suppose!
=>There seams to be a refreshing problem when using “setWindowsOpaque(window, false)” mode…
Max
March 3rd, 2008 at 5:55 am
Max, please try painting your graphics onto, say, a JPanel (through the overridden protected paintComponent(Graphics) method), rather than directly onto the JWindow. Of course, the panel should be added to the JWindow, and the panel should be:
1) made non-opaque: jpanel.setOpaque(false);
2) have the double buffering turned off: jpanel.setDoubleBuffered(false);
In tis case invoking the jpanel.repaint() method should work as expected.
March 4th, 2008 at 1:49 am
Ok, the paiting works, BUT the window isn’t transluent then…
The window paints a white background if I add a JPanel…
March 4th, 2008 at 8:31 am
Max, see my followup entry. When you add a panel, it is considered a control (as Anthony says) and you need to set it to non-double buffered and non-opaque.
March 4th, 2008 at 10:21 am
FYI, there’s a couple of issues that you need to watch out for until they get fixed:
6670644: non-opaque AWT frames don’t get repainted once shown
6670649: Swing JFrames don’t get repainted once shown if JFrame.repaint() is called
Dmitri
March 14th, 2008 at 4:45 pm
Hi there, i’m trying to learn some gui programming using textpad. I tried to compile the codes but not able to locate awtutilities even after i had installed the beta 13. Can anyone point to me what maybe missing ? Thank you so much.
March 14th, 2008 at 6:05 pm
Ryuusei – how do you compile your app? If it is from the command prompt, type “java -version”. You should see something like this:
java version “1.6.0_10-beta”
Java(TM) SE Runtime Environment (build 1.6.0_10-beta-b13)
Java HotSpot(TM) Client VM (build 11.0-b11, mixed mode, sharing)
Otherwise, you don’t use the correct javac to compile your classes.
March 15th, 2008 at 7:31 pm
Hi Kirill, Thanks for replying :) . Yup my version is as what you have mentioned. Hmm, i wonder wat’s missing lol
March 22nd, 2008 at 11:20 am
Ryuusei,
Did you try javac -version ?
-Carl
April 4th, 2008 at 5:14 pm
Way to go Sun! Nothing like advancing java by fixing a *7* years old bug! See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4479178
April 21st, 2008 at 8:57 am
Painting shaped windows is not using anti-aliasing. Looks pretty bad when you try an elliptical shape. Is there any way to get access to the Graphics object that AWTUtilities is using, to set hints? Would AWTUtilities use AA if it were turned on globally?
April 21st, 2008 at 9:17 am
Ken, please see the follow-up entry on soft clipping the window bounds.