JDK-4305619 : Add method Component.resizePaint that is called during a resize
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.3.0
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: windows_nt
  • CPU: x86
  • Submitted: 2000-01-19
  • Updated: 2006-06-14
Related Reports
Relates :  
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 good!)

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)

Comments
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. eric.hawkes@eng 2000-07-05
05-07-2000