Java Media Player - Final Chapter?
Join the DZone community and get the full member experience.
Join For FreeAs those who have been following my blog know, I have dug down deep into the coding of the GUI. I started there since I deemed that to be the most risky part given Java’s tendency for being slow, unless you know exactly what you do and on which platform. I have coded Swing for a long time so I thought that the problems would be quite a few but I was was confident I could code around them.
Seems I was wrong, or at least it looks like that right now. Congratulations to those who left comments in the line of “Why Java since it’s so slow and unreliable on the desktop”. The reasons are complicated but I will try to explain them below. Why? Because maybe if I write them down I can solve them?
First I made a GUI with a few cool, but subtle, effects. I have created the carousel component, the totally customized JScrollBar and both optimized glow and shadow effects. Everything was really fast and smooth, much because of the hardware accelerated image blits and scales. I am very happy with the carousel, it is every bit as fast as iTunes’ Cover Flow.
The second phase was about getting the side docked pullout sidebars to work. I had several fallback options for this that all should look the same as in the screen shots. And since I develop on the Mac using Java 1.6.0_07 everything went really smooth here as well.
To enable translucency you just set the background color to a color that have transparency (e.g. new Color(0, 0, 0, 0) and the rest is handled by the Mac Java implementation. I draw the shadows myself since I needed them to look the same for all platforms. It is easier if I make everything as one big window with the pullouts as normal components (and not heavyweight windows). On the Mac this work beautifully, fast and totally seamless.
Then I switched to test on Windows Vista and XP. There were some initial problems but that was mostly because of me and small inconsistencies that I wasn’t aware of. Like that you need to constantly poll for a new Graphics object from the component you want to animate on Windows. In OS X you could hold on to the same one. No biggie.
The trick of just setting a background color to get transparency doesn’t work in Windows, not even u10. Not sure why since it is such an obvious way to do it. Instead you have to add two lines, one which is in the protected sun libs. This makes this version update 10 and later only, unless of course I do it using reflection. The lines are:
window.setUndecorated(true);
com.sun.awt.AWTUtilities.setWindowOpaque(window, false);
With those lines pixels that aren’t painted with an opaque color will have the background show through.
But.. The performance totally went out the window (pun intended). With that last line in the code the GUI turned to dough though. Even selecting a row in the JTable was painfully slow and with a very noticeable lag. Unusable even. After an hour of investigation I found out, not from the documentation mind you, that when translucency is enabled the whole component tree of the frame will be repainted for every little local repaint!!! For instance, when the cursor blinks in a JTextField the whole frame will be repainted. How stupid is that! And not only that, it will be repainted to a buffer and then that buffer will be software copied to the screen! No wonder it was slow..
OK, I fired up mail to let my favorite Sun engineers know that Java 1.6.0_10 was not bug free just yet. I was surprised that they told me that this was the intended behavior! To make things worse they first even tried to convince me that it had to be this way because of how windows works. But after a few emails back and forth it became clear that it is Swing that has a problem with rendering to a translucent back buffer and there were no resources to address that. Bummer… It “may or may not be fixed in an update”…
So, I though that, well, me being a self appointed Swing/Java2D expert I could make my own back buffer and render to it. If I create my own RepaintManager I can intercept the small repaints and only repaint what is need to my own buffer. Then copy that buffer to the Frame, which in turn will be copied to the screen by Swing. But first I thought that I might do some performance testing, to be sure. It turns out that even a GUI that takes 0.0 ms to render is too slow for any window larger than 800×800 on my 2.4GHz one year old computer. So, even if I made the perfect algorithm that was infinitely fast it wouldn’t be enough. Just add a single JTextField to a translucent window of some size (like 1280×1024) and try to edit it… translucent windows in Java makes GHz feel like MHz. Dead end.
OK, being an expert and all I was not about to give up just yet. I praised OS X’s version of Java for not having any problems in the first place and took a warm shower, which is the place where most of my ideas come to. Ping! New idea!
I can use the normal window decorations (will look worse, but still ok) and have tool like dialogs for the pullouts. I began testing and at first it looked like it could be done. But it couldn’t… It turns out that there is no way to control the z-ordering of windows/frames/dialogs in Swing. The only control you have is that you can set a Window to be “alwaysOnTop”. Not very usable since that would disrupt the interaction with the other windows on the user’s desktop. Then I tried all the modality modes. You can actually make a tool window float on top of the main window, but not below it! I must have it below since the OS drawn shadow around the Window must be on top of my pullout or it will look very weird. Also, as soon as I pressed the pullout window the main window’s title bar would deactivate which is not the intended behavior. So, dead end there as well and another few hours wasted. And I was out of hot water to get new ideas (OK, not really. (About the water)).
This is where I am now. At a dead end. I could of course release only for the Mac, but no.. That would go against the whole thing of sharing music with your friends, not many of them have macs…
Actually when I was writing this I came up with another idea. Not sure it is viable but I might try it. I can set the main window and pullouts to clip with round rectangle shape. No window decorations. That means no problem with z-order or deactivated title bars since I draw the title bar and the windows will not overlap. Of course this means that there won’t be any shadows (not an option) but that might be solved with a kind of shadow-only window that has those much needed translucent pixels. Since those windows aren’t changed much, and they don’t host that many pixels in the first place it might actually work. I’ll think about it some more…
A lot of wining, I know, but I actually thought Sun would step up to the plate and make Java a viable choice for the desktop. And when I mean the desktop I’m not talking boring enterprise apps with crappy GUIs, I’m talking media players and widgets.
To add insult to injury it turns out that resizing windows on at least Vista turned sluggish with the jump from 1.6.0_07 to _10. Look at this post for more info: java.net forum link
Cheers,
Mikael Grev
ps. For those of you that come here for the screenshots, if you have managed to get through my ramblings here’s how the Media Player looks right now on the Mac. Everything, including the shadows, is drawn with Java2D (except the album art picture of course) and it is really really fast. Even the volume control is working…
Opinions expressed by DZone contributors are their own.
Comments