JDK-6670649 : Swing JFrames don't get repainted once shown if JFrame.repaint() is called
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6u10
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2008-03-03
  • Updated: 2011-03-15
  • Resolved: 2008-03-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7
6u10 b14Fixed 7Resolved
Description
Run the attached test:
  java -Dusenonop -Duseswing TSFrame
Or run 
  java TranslucentShapedFrameTest
and check non-opaque, 'use JFrame', and "create Frame"

You'll see that the JFrame that appears doesn't animate
as it's supposed to.

The paintComponent method is getting called.

Comments
SUGGESTED FIX http://sa.sfbay.sun.com/projects/java2d_data/6u10/6670649.0
05-03-2008

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); }
03-03-2008

WORK AROUND The workaround here is to call jpanel.repaint() instead of jframe.repaint(). (Note that a repaint of a single component will cause a repaint of the whole frame anyway) While this is a sufficient workaround for small apps it's difficult to implmeent in scenario's code.
03-03-2008

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)
03-03-2008