JDK-6497150 : Flickering by resizing JWindow or JFrame
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2006-11-24
  • Updated: 2011-02-16
  • Resolved: 2006-11-27
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_09-b03)
Java HotSpot(TM) Client VM (build 1.5.0_09-b03, mixed mode, sharing)

Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_04-b05)
Java HotSpot(TM) Client VM (build 1.4.2_04-b05, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
When resizing a JWindow, the content of that window flickers heavily.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached test case.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
During the resize, the the components inside the JWindows are displayed continuously without flicker.
ACTUAL -
During the resize, the background of the JWindow shows alternatively with the components inside causing the flickering effect.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JRootPane;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;


public class Test {

  
  private static void initUIManager(){
    // L&F and defaults
    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (Exception e) {}
  }
  
  
  public static class ResizableWindow extends JWindow {
    
    /**
     * Ctor.
     * @param p_Component is the main component in the Window.
     * @param p_Location is the location where this window should show
     */
    public ResizableWindow( Frame p_Frame,
                            JComponent p_Component,
                            Point p_Location){
      super( p_Frame);
      initUI();
      ((JComponent)getContentPane()).setBorder(BorderFactory.createEmptyBorder());
      getContentPane().add(p_Component, BorderLayout.CENTER);
      setLocation(p_Location);
    }
    
    private void initUI() {
      Border border = BorderFactory.createBevelBorder(BevelBorder.RAISED);
      int w = UIManager.getInt("InternalFrame.borderWidth");
      w = Math.max(w, 3) - 2;
      border = BorderFactory.createCompoundBorder(border,
              BorderFactory.createEmptyBorder(w, w, w, w));
      
      rootPane.setBorder(border);
      
      /* Register the resize listener. */
      ResizeListener resizeListener = new ResizeListener();
      addMouseListener(resizeListener);
      addMouseMotionListener(resizeListener);
    }
    
    protected int getDefaultCursor(MouseEvent p_Evt){
      return Cursor.DEFAULT_CURSOR;
    }
    
    
    /**
     * ResizeListener
     */
    private class ResizeListener extends MouseAdapter
                                 implements MouseMotionListener {


      private static final short RESIZE_E   = 1;
      private static final short RESIZE_W   = 2;
      private static final short RESIZE_N   = 4;
      private static final short RESIZE_S   = 8;
      private static final short MOVE       = 0x10;
      int                        resizing   = 0;
      private Rectangle          tempBounds = new Rectangle();




      public void mousePressed(MouseEvent evt) {
        resizing = getResizeDirection(evt);
        // if (resizing != 0) {
        // setIgnoreRepaint(true);
        // }
      }

      public void mouseReleased(MouseEvent evt) {
        resizing = 0;
        // setIgnoreRepaint(false);
        // validate();
        // repaint();
      }

      private short getResizeDirection(MouseEvent evt) {
        short direction = 0;
        int width = getWidth();
        int height = getHeight();
        Insets insets = getRootPane().getInsets();
        int mouseX = evt.getX();
        int mouseY = evt.getY();
        if (mouseX < insets.left) {
          direction |= RESIZE_W;
        }
        else if (mouseX > width - insets.right) {
          direction |= RESIZE_E;
        }
        if (mouseY < insets.top) {
          direction |= RESIZE_N;
        }
        else if (mouseY > height - insets.bottom) {
          direction |= RESIZE_S;
        }
        return direction;
      }

      public void mouseMoved(MouseEvent evt) {
        int cursorType = getCursorType(evt);
        setCursor(Cursor.getPredefinedCursor(cursorType));
      }

      private int getCursorType(MouseEvent evt) {
        short direction = getResizeDirection(evt);
        switch (direction) {
          case RESIZE_S :
            return Cursor.S_RESIZE_CURSOR;
          case RESIZE_E :
            return Cursor.E_RESIZE_CURSOR;
          case RESIZE_N :
            return Cursor.N_RESIZE_CURSOR;
          case RESIZE_W :
            return Cursor.W_RESIZE_CURSOR;
          case RESIZE_S | RESIZE_E :
            return Cursor.SE_RESIZE_CURSOR;
          case RESIZE_N | RESIZE_W :
            return Cursor.NW_RESIZE_CURSOR;
          case RESIZE_N | RESIZE_E :
            return Cursor.NE_RESIZE_CURSOR;
          case RESIZE_S | RESIZE_W :
            return Cursor.SW_RESIZE_CURSOR;
          default :
            int result = getDefaultCursor(evt);
            if (result==Cursor.MOVE_CURSOR){
              resizing = MOVE;
            }
            return result;
        }
      }

      public void mouseDragged(MouseEvent evt) {
        if ((resizing & MOVE) != 0) {
          //move not implemented
          return;
        }
        Rectangle bounds = getBounds(tempBounds);
        Point mouse = evt.getPoint();
        SwingUtilities.convertPointToScreen(mouse, ResizableWindow.this);
        if ((resizing & RESIZE_E) != 0) {
          bounds.width = evt.getX();
        }
        else if ((resizing & RESIZE_W) != 0) {
          bounds.width += bounds.x - mouse.x;
          bounds.x = mouse.x;
        }
        if ((resizing & RESIZE_S) != 0) {
          bounds.height = evt.getY();
        }
        else if ((resizing & RESIZE_N) != 0) {
          bounds.height += bounds.y - mouse.y;
          bounds.y = mouse.y;
        }
        
        if (bounds.getSize().height>=getMinimumSize().height &&
            bounds.getSize().width>=getMinimumSize().width){
          setBounds(bounds);
          validate();
          //repaint();
        }
      }
      
    } //ResizeListener
    
    
  } //ResizableWindow
  
  
  /**
   * @param args
   */
  public static void main(String[] args) {
    initUIManager();
    JFrame f = new JFrame();
    f.show();
    JLabel label = new JLabel("Test");
    label.setBackground(new Color(200,200,255));
    label.setForeground(new Color(200,255,200));
    ResizableWindow win = new ResizableWindow( f, label, new Point(200,200));
    win.setBackground(Color.red);
    win.pack();
    Dimension d = label.getPreferredSize();
    win.setSize(d.width*2, d.height*2);
    win.show();
  }
  
  
} //Test

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Providing the JWindow with a background of the same color than the main component minimize the visual impact of the bug.

Comments
EVALUATION Prior to fixing 4967886 AWT painted top levels, and Swing painted lightweights. This could lead to serious flickering when AWT first painted a component, then Swing. After fixing 4967886 Swing handles painting of any heavyweight Swing component (JFrame/JWindow/JDialog/JApplet), and flickers are gone. I'm closing this as a duplicate of 4967886.
27-11-2006