I have a problem where the background color I set on my JMEDesktop varies depending on whether the desktop is re-drawn beacause of a window move, or what it's initially drawn. I think the main problem is a difference in interpretation of alpha. This leaves an opaque trail behind the window when it moves, while the initial desktop is nicely translucent. Here is my set-up code (not based on the existing DesktopState):
// This works when the desktop is new, but not when it's refreshed by a window moving!
desktop.getJDesktop().setBackground(new Color(0.7f, 0.2f, 0.5f, 0.2f));
desktop.updateRenderState();
windows = new ArrayList<LiteDialog>();
GameStateManager.getInstance().attachChild(this);
I then go ahead and create a window on the desktop:
This just creates an empty window. When the window is dragged, it leaves an opaque, bright mauve color behind, as opposed to the translucent, dull image that the desktop initially has.
I had a similar issue with the Substance LAF and found several workarounds.
I first made the windows non-dragable, however I'm not sure if that is what you are looking for.
As the "trail" in Substance is actually a dithered transparent fill (which looks quite nice), I also experimented with maximizing and resetting the size of a window after it had been set to visible (which in your case would color the entire screen the purple).
Finally, calling:
jDesktop.getJDesktop().setOpaque(false);
jDesktop.getJDesktop().setBorder(null);
Will fix the issue, however I am not sure if you want to have a background behind the internal frame, as I have not encountered a purple trail in the default LAF.
I have only tested these in substance, but its worth a shot.
Lastly, based on my not too great knowledge of swing, you could probbably extend some class somewhere and take over yourself.
Thanks for the answer! I don't think the purple trail is intentional – it's a side effect of the desktop using two different colors. I think it might be using black by default, and then adding my configured desktop color on the expose events.
I tried adding the two lines you posted, but those don't help. I think the main problem is that the desktop starts out black, even when I configure another color, so some function to force the desktop to re-paint would probably do the trick.
Thanks for the answer! I don't think the purple trail is intentional -- it's a side effect of the desktop using two different colors. I think it might be using black by default, and then adding my configured desktop color on the expose events.
I tried adding the two lines you posted, but those don't help. I think the main problem is that the desktop starts out black, even when I configure another color, so some function to force the desktop to re-paint would probably do the trick.
If you just want to force a repaint, after setting the internal frame to visible scale it to cover the entire JMEDesktop and then back to its normal size.
Thanks again for the suggestion. However, I'm not so much interested in just getting it to work; I'm more interested in why it doesn't work, and how it's supposed to be done right.
When do you set the background color? Is it done in the awt-event-thread? If yes, it should repaint itself automatically. If no, you can call repaint on the JDesktop afterwards (still one should not access swing stuff from outside the awt thread). From the code you posted it seems you are creating/setting the swing stuff from another thread as you access the scenegraph there.
I'm using a single thread right now, so no, I'm not inside the AWT thread.
I tried adding repaint() after setting the background color. However, that didn't work, probably because it's not from within the AWT thread. What did work, though, was calling repaint() after adding/showing the internal window on the desktop. I don't know if this is by design, or whether it's just a race condition waiting to happen, though. The documentation doesn't talk about the AWT thread in general, so I'd appreciate any guidance on this subject.
The general policy for awt/swing is: never touch any awt/swing from any other thread than the event queue. If you do not adhere to that you sometimes need some crude workarounds. So my suggestion would be to wrap all your swing code into an invokeLater or invokeAndWait.
That should probably be documented in the JMEDesktop class. At least in the getJDesktop() accessor, if not elsewhere.
Also, how can the getters (like getFocusOwner()) be at all safe, if they can be changed by another thread before you can actually do anything with them?
how can the getters (like getFocusOwner()) be at all safe, if they can be changed by another thread
I think that is precisely why you shouldn't access Swing outside the awt/Swing thread. Just use SwingUtilities.invokeLater(Runnable).
As Irrisor said, this is a general rule with Swing, not JMEDesktop, which is probably why it is undocumented.
Actually there is a comment in HelloJMEDesktop, but if there is no proper javadoc in JMEDesktop. That should be changed, maybe by copying the following into the getJDesktop() doc:
Only access the Swing UI from the Swing event dispatch thread! See SwingUtilities.invokeLater() and http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html for details.
And while we're at it, TestJMEDesktop could use a comment in this style too.
I think the idea would be to put the while get, use/modify, set into an invokeLater call to be safe… In other words, invokeLater will guarantee that all the calls within it will have a consistent execution.