EVALUATION
Animating non-opaque JFrames doesn't work in some cases.
My example has JFrame with a (non-opaque, non-double-buffered) JPanel.
If a jframe.repaint() is called instead of
jpanel.repaint(), we eventually end up in
RepaintManager.paintDirtyRegions, which calls updateWindows().
There we iterate through the dirty components, find their
Window ancestors and call updateWindow on them.
The problem is that if the dirty component _is_ a JFrame, then
SwingUtilities.getWindowAncestor() returns null because
it doesn't expect the passed component to be a Window so
we don't add it to the list of windows to be updated.
I don't know if this is an expected behavior from
getWindowAcnestor(), but it looks suspicious to me.
It works if the following fix is applied to RepaintManager.java:
*** RepaintManager.java: 1.72
--- RepaintManager.java
***************
*** 723,729 ****
Set<Window> windows = new HashSet<Window>();
for (Component dirty : dirtyComponents) {
! Window window = SwingUtilities.getWindowAncestor(dirty);
if (window != null) {
windows.add(window);
}
--- 723,732 ----
Set<Window> windows = new HashSet<Window>();
for (Component dirty : dirtyComponents) {
! Window window = dirty instanceof Window ?
! (Window)dirty :
! SwingUtilities.getWindowAncestor(dirty);
!
if (window != null) {
windows.add(window);
}
Another quirks I found:
- you must set your component to be single-buffered
by calling setDoubleBuffered(false).
Since apparently this property doesn't propagate to children,
it has to be done manually for all children of your
non-opaque JFrames.
It would be better if this was done automatically: when a jcomponent
is added to a non-opaque frame, it should automatically be switched
to be single-buffered. If the status of the frame changes to
opaque, it should probably reset the property for all children.
- in my JPanel.paintComponent() I had to do
g.clearRect(0,0,w,h) first, or call super.paintComponent()
- make sure to set your components' opaqueness to 'false'
by calling setOpaque(false)
|
SUGGESTED FIX
*** RepaintManager.java: 1.72
--- RepaintManager.java
***************
*** 723,729 ****
Set<Window> windows = new HashSet<Window>();
for (Component dirty : dirtyComponents) {
! Window window = SwingUtilities.getWindowAncestor(dirty);
if (window != null) {
windows.add(window);
}
--- 723,732 ----
Set<Window> windows = new HashSet<Window>();
for (Component dirty : dirtyComponents) {
! Window window = dirty instanceof Window ?
! (Window)dirty :
! SwingUtilities.getWindowAncestor(dirty);
!
if (window != null) {
windows.add(window);
}
|