Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4096745
Votes 1
Synopsis disable()/enable() make AWT [lightweight] components blink
Category java:classes_awt
Reported Against 1.2 , 1.3 , 1.4 , 1.1.4 , 1.3.1_04
Release Fixed 1.3.1_05, 1.4.0_02(Bug ID:2118971) , 1.4.1(hopper-beta) (Bug ID:2118972)
State 10-Fix Delivered, request for enhancement
Priority: 4-Low
Related Bugs 4407186 , 4673900 , 4684354
Submit Date 03-DEC-1997
Description




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)
======================================================================




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)
======================================================================
Work Around
N/A
Evaluation
Definitely a problem.  Needs further investigation.

  xxxxx@xxxxx   1999-08-11



  xxxxx@xxxxx  
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.
  xxxxx@xxxxx   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.
  xxxxx@xxxxx   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.  

  xxxxx@xxxxx   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
-   xxxxx@xxxxx   2002-04-05
Comments
  
  Include a link with my name & email   

Submitted On 04-FEB-1998
lichunyue
Who will be kind enough to help me how to make blink AWT component?


Submitted On 28-JAN-2002
alexc1
I've seen this on our AWT-based applications that runs 
(slowly) using Personal Java on a handheld device. It is 
particularly noticable because the drawing performance of 
the device is not great. It looks terrible! I'm sure that 
performance would improve a lot if AWT only updated the 
display when obsolutely necessary.


Submitted On 23-FEB-2004
albo
Currently using 1.4.2-03 and this is still a problem.  
Calling setEnabled(true/false) causes major window 
flashes and can cause windows to be painted behind 
other windows.  Has this been re-raised yet?



PLEASE NOTE: JDK6 is formerly known as Project Mustang