JWindow resizing flicker



I've made a resizable JWindow class for some of my GUI needs and I'm
facing problem with flicker during the resize (I validate the window
and update its graphics when I change its bounds). I'm trying it with
Sun's Java 1.4 and 5 on Windows.

After some testing and research I find the flicker comes from the fact
the system peer clears its background prior the window draws its
content and that seems unavoidable. I've tried using the
Component.setIgnoreRepaint(true) during resizing so no flickering
occurs but the window graphics is cleared and I've wondered is there a
way to achieve behavior as with JFrames, for example? With a JFrame I
notice a snapshot of the graphics painted last prior the sizing has
begun is visible and plain color is only drawn for regions added to if
the sizing extends the window width and/or height.

Here's my resizable window class:

//package ;

import java.awt.Cursor;
import java.awt.Frame;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.BorderFactory;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;

public class ResizableWindow extends JWindow {

public ResizableWindow(Frame owner) {
super(owner);
initUI();
}

public ResizableWindow(Window owner) {
super(owner);
initUI();
}

private void initUI() {
/* Set a nice border - try to use the internal frame border
* (used inside JDesktopPane) which should mimic the native
* frame border when using the system look and feel. */
Border border = UIManager.getBorder("InternalFrame.border");
if (border == null) {
/* Fallback to this 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);
}

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;

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) {
short direction = getResizeDirection(evt);
int cursorType = getCursorType(direction);
setCursor(Cursor.getPredefinedCursor(cursorType));
}

private int getCursorType(int direction) {
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:
return Cursor.DEFAULT_CURSOR;
}
}

public void mouseDragged(MouseEvent evt) {

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;
}
setBounds(bounds);
validate();
repaint();
}

}

}

--
Stanimir

.



Relevant Pages

  • JFrame Resize Issues (Redux)
    ... However, when the LookAndFeel is set, Java's Window Manager ... public int OffSetX = 0; ... private Rectangle positRectangle; ... public void componentHidden{ ...
    (comp.lang.java.programmer)
  • how to resize child window?
    ... i set my window to be the parent of a 'Notepad' window. ... private System.Windows.Forms.CheckBox checkBoxParent; ... int FindWindow; ... private void checkBoxParent_CheckedChanged(object sender, System.EventArgs ...
    (microsoft.public.win32.programmer.gdi)
  • Re: how to resize child window?
    ... this does not change the focus of any window. ... > private System.Windows.Forms.CheckBox checkBoxParent; ... > private void InitializeComponent() ... > int FindWindow; ...
    (microsoft.public.win32.programmer.gdi)
  • Re: CreateProcess() its extermely slow
    ... I notice that if my application has no Window, ... int APIENTRY _tWinMain(HINSTANCE hInstance, ... LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, ... LPARAM lParam) ...
    (microsoft.public.vc.mfc)
  • Re: DC styles
    ... display DC each time the application must draw in a window. ... Private DCs ... An application can retrieve the handle of the private DC by using the ... application must incorporate the update region either by calling ...
    (alt.lang.asm)