Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / GUI / March 2006

Tip: Looking for answers? Try searching our database.

JWindow resizing flicker

Thread view: 
Stanimir Stamenkov - 08 Feb 2006 20:20 GMT
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();
       }

   }

}

Signature

Stanimir

Stanimir Stamenkov - 05 Mar 2006 14:34 GMT
> I've made a resizable JWindow class for some of my GUI needs and I'm
> facing problem with flicker during the resize
[...]

Here's simple example using JFrame instead (see some description at the
bottom) one may try with:

-----TestFrame.java
//package ;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class TestFrame extends JFrame {

   TestFrame() {
       super("Test Frame");
       setName("MainFrame");
       setDefaultCloseOperation(EXIT_ON_CLOSE);
       initUI();
   }

   private void initUI() {
       initMenuBar();

       Container contentPane = getContentPane();
       JDesktopPane workspace = new JDesktopPane();
       contentPane.add(workspace, BorderLayout.CENTER);

       JInternalFrame iframe = new JInternalFrame("Something",
               true, true, true, true);
       iframe.setBounds(40, 40, 240, 180);
       iframe.setVisible(true);
       workspace.add(iframe);

       iframe = new JInternalFrame("Other thing",
               true, true, true, true);
       iframe.setBounds(10, 10, 240, 180);
       iframe.setVisible(true);
       workspace.add(iframe);
   }

   private void initMenuBar() {
       JMenuBar menuBar = new JMenuBar();
       JMenu toolsMenu = menuBar.add(new JMenu("Tools"));
       toolsMenu.setMnemonic(KeyEvent.VK_O);

       toolsMenu.add(new AbstractAction("Exit") {
           {
               putValue(MNEMONIC_KEY,
                        Integer.valueOf(KeyEvent.VK_X));
               putValue(ACCELERATOR_KEY,
                        KeyStroke.getKeyStroke(KeyEvent.VK_Q,
                                InputEvent.CTRL_DOWN_MASK));
           }
           public void actionPerformed(ActionEvent evt) {
               exit();
           }
       });
       setJMenuBar(menuBar);
   }

   public void exit() {
       System.exit(0);
   }

   public static void main(String[] args) {
       SwingUtilities.invokeLater(new Runnable() {
           public void run() {
               try {
                   initAndShowUI();
               } catch (Exception ex) {
                   ex.printStackTrace();
               }
           }
       });
   }

   static void initAndShowUI() {
       //try {
       //    UIManager.setLookAndFeel(UIManager
       //            .getSystemLookAndFeelClassName());
       //} catch (Exception ex) {
       //    ex.printStackTrace();   // continue though
       //}

       //Toolkit.getDefaultToolkit().setDynamicLayout(true);

       JFrame.setDefaultLookAndFeelDecorated(true);

       Window mainWindow = new TestFrame();
       mainWindow.setSize(480, 360);
       mainWindow.setLocationRelativeTo(null);   // center on screen
       mainWindow.setVisible(true);
   }

}
-----TestFrame.java--

This example is what I'm trying to accomplish with a JWindow which
doesn't provide a native decoration and controller for resizing the
window. Using the Metal L&F, the native frame decoration is replaced
with a decoration implemented by the L&F for the frame's rootPane - the
flicker during resizing is apparent. The difference should be sizing
events don't come from the native system but from within Swing.

I've tried commenting out:

   //JFrame.setDefaultLookAndFeelDecorated(true);

and setting:

   Toolkit.getDefaultToolkit().setDynamicLayout(true);

where during resizing, painting events are emitted pretty often, I
guess - no flickering is visible whatsoever.

Signature

Stanimir

Stanimir Stamenkov - 05 Mar 2006 14:52 GMT
> -----TestFrame.java
[...]
>     private void initUI() {
>         initMenuBar();
[quoted text clipped - 15 lines]
>         workspace.add(iframe);
>     }
[...]
> -----TestFrame.java--

For a more robust example one may try replacing the JDesktopPane with a
text component inside a JScrollPane so the entire text will be reflowed
and redrawn during a resize:

   private void initUI() {
       initMenuBar();

       Container contentPane = getContentPane();
       JTextPane textPane = new JTextPane();
       try {
           textPane.setPage(new URL("http://www.w3.org/TR/html4/"));
           textPane.setEditable(false);
       } catch (IOException ioex) {
           ioex.printStackTrace();
       }
       JScrollPane scrollPane = new JScrollPane(textPane);
       contentPane.add(scrollPane, BorderLayout.CENTER);
   }

> I've tried commenting out:
>
[quoted text clipped - 6 lines]
> where during resizing, painting events are emitted pretty often, I
> guess - no flickering is visible whatsoever.

Signature

Stanimir

Stanimir Stamenkov - 09 Mar 2006 21:44 GMT
>> I've made a resizable JWindow class for some of my GUI needs and I'm
>> facing problem with flicker during the resize
[quoted text clipped - 4 lines]
>
> -----TestFrame.java
[...]

Have somebody tried the example and does everybody experience the
flicker? I've found there's no flicker on 2 of around 10 systems I've
tried with and now wonder what's the cause even more.

Signature

Stanimir



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.