JDK-4096745 : disable()/enable() make AWT [lightweight] components blink
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.1.4,1.2.0,1.3.0,1.3.1_04,1.4.0
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS:
    generic,solaris_2.5.1,windows_nt,windows_2000 generic,solaris_2.5.1,windows_nt,windows_2000
  • CPU: x86,sparc
  • Submitted: 1997-12-03
  • Updated: 2004-09-16
  • Resolved: 2002-05-09
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.
Other Other Other
1.3.1_05 05Fixed 1.4.0_02Fixed 1.4.1Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Description

Name: rm29839			Date: 12/03/97


Hi!

When enable()/disable() of most AWT components is
called [ex: Button, TextField, etc] - they are doing
repaint(). They blink becouse of it.
[repaint() at the start probably clears whole
components area].

Example - when calling Button's disable() method -
text of Button nicely changes to gray ...and
WHOLE Button's area is repainted! Although nothing
changed there and nothing need to be repainted!

Becouse of it - application, which enables/disables
components alot (on Containers, which are shown) looks a bit odd.

It would be great if enable()/disable() of AWT components
will not call repaint() in this way.
[maybe call something like update()
which will paint ONLY changed parts. For example
to disable Button - it need only to paint gray
text over current text, and there is no need to clear
nothing at all.]

 Thanks! 8-)

---

 - leon
(Review ID: 21207)
======================================================================

Name: skT88420			Date: 06/17/99


When issuing a setEnabled() call on any component the 
entire component is repainted. For smaller components like 
a JTextField and JMenuItem this is annoying. For larger 
components like JFrame or JDialog the blink caused by 
the repaint makes the application completely unacceptable 
to our user group. 

An analysis of the Java source reveals that in fact every 
component is repainted on a enable/disable:

Taken from awt_component.cpp:

JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_enable(JNIEnv *env, jobject self)
{
    jint pData;
    JNI_CHECK_PEER_RETURN(self);
    AwtComponent* p = (AwtComponent*)pData;
    ::EnableWindow(p->GetHWnd(), TRUE);
    ::InvalidateRect(p->GetHWnd(), NULL, TRUE); // Bug #4038881 Labels don't enable and disable properly
    CriticalSection::Lock l(p->GetLock());
    p->VerifyState();
}

The InvalidateRect call was apparently added because of a 
bug in labels. The side effect is that instead of 
only repainting labels everything is being repainted. 

For some reason you have had difficulty reproducing this 
bug because it has been reported several times before:

4145715, 4024346, 4096745

Please make every effort to reproduce this bug, it is 
critical that we have it fixed as we see no workaround. 

I would be happy to suggest a fix, fly out and fix it, 
in general do anything to see that it be fixed.
(Review ID: 84484)
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.3.1_05 1.4.0_02 hopper-beta FIXED IN: 1.3.1_05 1.4.0_02 hopper-beta INTEGRATED IN: 1.3.1_05 1.4.0_02 hopper-beta
22-09-2004

EVALUATION Definitely a problem. Needs further investigation. michael.martak@Eng 1999-08-11 Name: ssR10077 Date: 07/26/2000 ###@###.### The last parameter in ::InvalidateRect(p->GetHWnd(), NULL, TRUE) means clearing background before paint. Since it is TRUE the window flickers. The fix of this problem is to set it FALSE. ====================================================================== This is still reproducable in Merlin and Hopper. It was caused by adding back the shouldClearRectBeforePaint() back into the peers. This will be fixed in Hopper. ###@###.### 2002-01-14 As of Hopper 1.4.1 (Build 02) the blinking only occurs when lightweight components are added to the container (i.e. Swing). See attached test case (simpleFrame.java) for demonstration. Press the Dialog button. ###@###.### 2002-03-08 When Component.enable() is called, we call ::InvalidateRect(GetHWnd(), NULL, FALSE); in awt_Component.cpp ::Enable which generates a WM_PAINT. When we process the resulting paint event, we erase the background for all lightweight components, since we have no way of distinguishing between those lw components that need the background erased (like all of swing), and those that do not. The ultimate fix is to provide a public method in Component.java that clears the background of the Component. Subclasses could override the method to either clear or prevent clearing of the component. See 4519407. That way, client code can make the distinction about whether the background should be erased or not. Note: the fix that was put into the 1.3.1 source tree should not be ported to the 1.4 source tree. The reason is that in 1.3.1, we were erasing the background on the toolkit thread and on the EDT. That caused problems on dual-processor systems. So, on 1.4, we only erase on the EDT. I don't see a good solution for 1.4. ###@###.### 2002-03-11 As we are aware that the blinking is caused by the line ::InvalidateRect(GetHWnd(), NULL, FALSE); in AwtComponent.Enable(). This line is introduced to fix bug #4038881 " Labels don't enable and disable properly". If we back out this fix then we don't see the blinking. And the fix for awt labels should get into AwtLabel.Enable() not into AwtComponent.Enable as it is now in 1.4 and upward - ###@###.### 2002-04-05
05-04-2002

SUGGESTED FIX add method WWindowPeer.java public boolean shouldClearRectBeforePaint() { return false; } This will cause a painting regression in Hopper because the native background erasing has been removed. ###@###.### 2002-02-11 For 1.4 : Move the fix for bug #4038881 to awt_Label.cpp (Enable) from awt_Component.cpp - AwtComponent.Enable(). ###@###.### 2002-04-05
11-02-2002