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: 4305619
Votes 15
Synopsis Add method Component.resizePaint that is called during a resize
Category java:classes_awt
Reported Against kestrel-beta
Release Fixed
State 6-Fix Understood, request for enhancement
Priority: 4-Low
Related Bugs 4077991
Submit Date 19-JAN-2000
Description
NOTE: this bug was originally part of 4274930, but it contained a couple of bugs, so I moved this into its own place.
-sky
--------------------------------

java version "1.3beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3beta-O)
Java(TM) HotSpot Client VM (build 1.3beta-O, mixed mode)
The java.awt.Component.reshape(...) method forces a full repaint of both the
old area and the new area occupied by the component.

Some components do not need to be entirely repainted when they are resized. For
example when resizing a spreadsheet application only the newly exposed region
needs to be painted, to repaint the previously exposed region causes a horrible
flicker and is a performance hit.

Some layouts do not need the old component area repainted.

Some programmers will come up with better ways of repainting their components
when they have been resized.

Anyone making a java application like a word processor or a spreadsheet needs
to be able to control what painting is being done when a resize is made. It is
not acceptable for the whole component to flicker when a resize is made.

There is no convienient way to overide this method, because it is also the only
way to update the x, y, width and height, which are package protected.


Pseudo code to explain the changes....

Add the following to java.awt.Component....

////////////////////////////////////////////////////////////////////


// this method is intented to be overridden by programmers
   
public void resizePaint(Rectangle oldRect, Rectangle newRect)
{
   parent.repaint(oldRect.x, oldRect.y, oldRect.width, oldRect.height);
   repaint(newRect.x, newRect.y, newRect.width, newRect.height);
}
	    


Also change the last few lines of code in the method...

    reshape(int x, int y, int width, int height)

    to the effect that

    if (isLightweight && isShowing())
    {
        // Repaint the old area ...
        parent.repaint(oldParentX, oldParentY, oldWidth, oldHeight);
        // ... then the new (this areas will be collapsed by
        // the ScreenUpdater if they intersect).
        repaint();
    }

    becomes...
    
    if (isLightweight && isShowing())
    {
        resizePaint(Rectangle oldRect, Rectangle newRect);
    }

       
    
//////////////////////////////////////////////////////////////////////

Other changes needed.

1)

    Stop the repaint messages coalessing
    or change the above calls from repaint to paint(g);

    The reason :
    
    If I resize my hypothetical spreadsheet by 3 pixels in width
    it means that the program needs to repaint both scrollbars
    and a 3 pixel strip of the grid component.

    If it just does that it will be fast and flicker free.

    If you coaless the calls it results in the entire grid being
    repainted, one big flicker and performance hit.

    So don't coaless the call !!

    ( of course the programmer can override the new method and
    call paint(g) directly)

2)
    Remove the call to repaint() in the following java.awt.Window code...

    
    void dispatchEventImpl(AWTEvent e) {
         switch(e.getID()) {
          case FocusEvent.FOCUS_GAINED:
            setFocusOwner(this);
            break;
          case ComponentEvent.COMPONENT_RESIZED:
            invalidate();
            validate();
            repaint();
            break;

    The reason :
        validate will have already made calls to repaint.
        this call causes a big flicker and performance hit
        

////////////////////////////////////////////////////////////////
(Review ID: 97302)
================================================================================
D:\aWork\java\src13b>java -version
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-I)
Java HotSpot(TM) Client VM (build 1.3-I, mixed mode)

When a JWindow is resized with the setBounds(...) function it causes the
background to be painted over any existing components. This results in flicker.

I have created a test that moves a window across the screen then resizes itself.
You will notice the flicker when it starts with resize itself.

This bug makes it very tough to create JWindow containers that are resizable.

(p.s. I did notice this latest JRE 1.3 I tested with eliminated the flicker as
it moved across the screen, that is a  customer !)

import javax.swing.*;
public class TestClearRect extends JWindow {
	
public static void main(String[] args) {
	TestClearRect aTestFrame = new TestClearRect();
	JPanel aPanel = new JPanel();
	aPanel.setBackground(java.awt.Color.black);
	aTestFrame.setContentPane( aPanel );
	aTestFrame.setSize( 400,400 );
	aTestFrame.setVisible(true);
	aTestFrame.moveMe();
}
public void moveMe() {
	//lets move this frame on the screen
	Thread aThread = new Thread() {
	public void run() {
		try {
			yield();
			sleep( 1000 );
		} catch ( InterruptedException e ) {
		}
		Runnable aMove = new  Runnable() {
			public void run() {
				if ( getLocation().x > 300 ) {
					setBounds( getLocation().x , 20 ,
(int)getSize().getWidth() - 8 , (int) getSize().getHeight());
				} else {
					setLocation( getLocation().x + 10 , 20
);
				}
			}
		};
		for (int i = 0; i < 80; i++){
			try {
				yield();
				sleep( 500 );
			} catch ( InterruptedException e ) {
			}
			javax.swing.SwingUtilities.invokeLater( aMove );
		}
	}
	};
	aThread.start();

	
}
public void update( java.awt.Graphics g )  {
	paint( g );
}
}

(Review ID: 100026)
Work Around
N/A
Evaluation
Sounds like two issues are mentioned:  

1)  dynamic resizing: 4077991 

2)  on a diagonal resize, we used to repaint the entire window because we 
took the rectangle union of the newly exposed vertical and horizontal strips.  
We don't do that any more (as of 1.3).  See 4174831, 4227116 for example.  

I'll have to consider the usefulness of this rfe in light of 4077991 and 
the aforementioned bugs.  

  xxxxx@xxxxx   2000-07-05
Comments
  
  Include a link with my name & email   

Submitted On 18-MAR-2000
joerg.wassmer
Without this bug, it would be possible to write a full 
featured subclass of JInternalFrame, that handles it's own 
(private) Window parent, so that you wouldn't be in need to 
use JFrame anymore, which breaks the L&amp;F. Currently you can
use JInternalFrame for such work only, if you aren't in need
of resizing it.
There are also two other things missing: 
1. A 'getAllWindows()' method in java.awt.Windows, like 
Frame.getAllFrames(). 
2. A public accessible method to set JInternalFrame working
modal (like Dialog). I've written a modal JInternalFrame, 
but it makes me somewhat nervous, because I can't be sure
about compatibility with future JDK's.


Submitted On 26-DEC-2000
dbmartin
This bug, 4077991, and the others mentioned are NOT getting 
the attention they deserve.  This is NOT a request for an 
enhancement.  It is a DEFECT, and a serious one.

When will this heinous flicker be dealt with right?  Not to 
be snippy, but I'd like an e-mail from someone at Sun who 
has an answer...



Submitted On 18-APR-2007
For anyone tracking this topic, try running these lines before any windows are built:

Toolkit.getDefaultToolkit().setDynamicLayout(true);
System.setProperty("sun.awt.noerasebackground", "true");



PLEASE NOTE: JDK6 is formerly known as Project Mustang