Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6329277

Poor performance of Swing dynamic layout when resizing a JFrame

    XMLWordPrintable

Details

    • Cause Known
    • x86
    • windows_xp

    Description

      FULL PRODUCT VERSION :
      java version "1.6.0-ea"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-ea-b46)
      Java HotSpot(TM) Client VM (build 1.6.0-ea-b46, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Windows XP SP2

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      2.8 GHz Pentium 4, 512mb RAM, GeForce4 Ti 4200 with AGP 8x

      A DESCRIPTION OF THE PROBLEM :
      When resizing JFrames with your mouse and after setting
      java.awt.Toolkit.getDefaultToolkit().setDynamicLayout(true) or when using Mustang (dynamic layout is on by defualt) performance appears slow. For instance if you have a large JTable you shrink the window you can easily "eat" the scrollbars (so that they are not visible) if you are shrinking from the bottom right corner. When you are growing the window from the same corner you can see a large gap between the scrollbars (which shouldn't be visible because the table is supposed to take up the complete area).

      Surprisingly, embedding the Swing component within SWT produces much better resize performance than if you use a JFrame.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :

      This procedure is for Windows. I don't know what the results are for other platforms but they may have the same problem. I don't think this procedure will work on Mac OS X because of problems with SWT embedding Swing on that platform.

      SwingSWTComparison01.java is the Same code as in the Snippet154.java discussed earlier except it has a non-SWT version for comparison.
      SwingSWTComparison02.java does the same thing as Comparison but instead of a JTable it simply paints an oval which fills the window.

      To run the comparison code below:

      1) Download eclipse 3.1 (needed for SWT) at http://eclipse.org/downloads/index.php
      2) Unzip the downloaded file and run "eclipse.exe" located in the folder where you extracted it
      3) Create a new project: File>New>Project>Java Project click "Next"
      4) Choose a project name (ie. "Test SWT Swing Project") click "Finish"
      5) Right click the project then select Properties>Java Build Path>Libraries
      6) Click "Add Library..." then select "Standard Widget Toolkit (SWT)" and click "Next" then "Finish"
      7) Create a new Class File>New>Class enter "Comparison" as the name and click "Finish"
      8) Open the new SwingSWTComparison01.java file and insert the test code below
      9) From the menu-bar select Run>Run As>Java Application
      10) When the program runs resize the windows with your mouse on each edge and corner and note the performance difference between the Swing and the Swing embedded in SWT
      11) Repeat steps 7-9 with SwingSWTComparison02.java

      Compare with the same situation using only a JFrame: It is obvious that the resize performance is much worse. It is many times slower to re-layout the the components so that they fill the JFrame properly.

      Different types of Components may show a more dramatic performance difference.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------

      ///SwingSWTComparison01.java

      import java.awt.BorderLayout;
      import java.awt.Frame;
      import java.awt.Graphics;
      import java.awt.Panel;
      import javax.swing.*;

      import java.util.Vector;

      import org.eclipse.swt.*;
      import org.eclipse.swt.widgets.*;
      import org.eclipse.swt.layout.*;
      import org.eclipse.swt.awt.SWT_AWT;

      public class SwingSWTComparison01 {

      public static void main(String[] args) {
      // This is required for the SWT example to not flicker
      try {
      System.setProperty("sun.awt.noerasebackground", "true");
      } catch (NoSuchMethodError error) {
      }

      java.awt.Toolkit.getDefaultToolkit().setDynamicLayout(true);

      runSwing(createTable("Swing"));
      runEmbeddedSWT(createTable("SWT"));
      }

      private static void runSwing(JTable table) {
      JFrame frame = new JFrame();
      Panel panel = new Panel(new BorderLayout()) {
      public void update(java.awt.Graphics g) {
      /* Do not erase the background */
      paint(g);
      }
      };
      frame.getContentPane().add(panel);
      frame.setTitle("Swing JFrame");
      frame.setSize(400, 400);
      JRootPane root = new JRootPane();
      panel.add(root);
      java.awt.Container contentPane = root.getContentPane();

      // JTable table = createTable();
      JScrollPane scrollPane = new JScrollPane(table);
      contentPane.setLayout(new BorderLayout());
      contentPane.add(scrollPane);

      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);
      }

      public static void runEmbeddedSWT(JTable table) {
      final Display display = new Display();
      final Shell shell = new Shell(display);
      shell.setLayout(new FillLayout());
      shell.setSize(0, 0);
      shell.setText("Swing embedded in SWT");
      shell.setSize(400, 400);
      shell.setLocation(400, 400);

      Composite composite = new Composite(shell, SWT.NO_BACKGROUND | SWT.EMBEDDED
      );

      /*
      * Set a Windows specific AWT property that prevents heavyweight
      * components from erasing their background. Note that this is a global
      * property and cannot be scoped. It might not be suitable for your
      * application.
      */

      /* Create and setting up frame */
      Frame frame = SWT_AWT.new_Frame(composite);
      Panel panel = new Panel(new BorderLayout()) {
      public void update(java.awt.Graphics g) {
      /* Do not erase the background */
      paint(g);
      }
      };
      frame.add(panel);
      JRootPane root = new JRootPane();
      panel.add(root);
      java.awt.Container contentPane = root.getContentPane();

      // JTable table = createTable();
      JScrollPane scrollPane = new JScrollPane(table);
      contentPane.setLayout(new BorderLayout());
      contentPane.add(scrollPane);

      shell.open();
      while (!shell.isDisposed()) {
      if (!display.readAndDispatch())
      display.sleep();
      }
      display.dispose();
      System.exit(0);
      }

      private static JTable createTable(String type) {
      /* Creating components */
      int nrows = 1000, ncolumns = 10;
      Vector rows = new Vector();
      for (int i = 0; i < nrows; i++) {
      Vector row = new Vector();
      for (int j = 0; j < ncolumns; j++) {
      row.addElement("Item " + i + "-" + j);
      }
      rows.addElement(row);
      }
      Vector columns = new Vector();
      for (int i = 0; i < ncolumns; i++) {
      columns.addElement("Column " + i);
      }
      JTable table = new JTable(rows, columns);
      // JTable table = new RecordingJTable(type, rows, columns);
      table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
      table.createDefaultColumnsFromModel();
      return table;
      }

      }


      ///SwingSWTComparison02.java

      import java.awt.BorderLayout;
      import java.awt.Component;
      import java.awt.Frame;
      import java.awt.Graphics;
      import java.awt.Panel;

      import javax.swing.JFrame;
      import javax.swing.JPanel;
      import javax.swing.JRootPane;

      import org.eclipse.swt.SWT;
      import org.eclipse.swt.awt.SWT_AWT;
      import org.eclipse.swt.layout.FillLayout;
      import org.eclipse.swt.widgets.Composite;
      import org.eclipse.swt.widgets.Display;
      import org.eclipse.swt.widgets.Shell;

      public class SwingSWTComparison02 {

      public static void main(String[] args) {
      // This is required for the SWT example to not flicker
      try {
      System.setProperty("sun.awt.noerasebackground", "true");
      } catch (NoSuchMethodError error) {
      }

      java.awt.Toolkit.getDefaultToolkit().setDynamicLayout(true);

      runSwing(createComponent());
      runEmbeddedSWT(createComponent());
      }

      private static void runSwing(Component comp) {
      JFrame frame = new JFrame();
      frame.getContentPane().add(comp);
      frame.setTitle("Swing JFrame");
      frame.setSize(400, 400);

      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);
      }

      public static void runEmbeddedSWT(Component comp) {
      final Display display = new Display();
      final Shell shell = new Shell(display);
      shell.setLayout(new FillLayout());
      shell.setSize(0, 0);
      shell.setText("Swing embedded in SWT");
      shell.setSize(400, 400);
      shell.setLocation(400, 400);

      Composite composite = new Composite(shell, SWT.NO_BACKGROUND | SWT.EMBEDDED
      );

      /*
      * Set a Windows specific AWT property that prevents heavyweight
      * components from erasing their background. Note that this is a global
      * property and cannot be scoped. It might not be suitable for your
      * application.
      */

      /* Create and setting up frame */
      Frame frame = SWT_AWT.new_Frame(composite);
      Panel panel = new Panel(new BorderLayout()) {
      public void update(java.awt.Graphics g) {
      /* Do not erase the background */
      paint(g);
      }
      };
      frame.add(panel);
      JRootPane root = new JRootPane();
      panel.add(root);
      java.awt.Container contentPane = root.getContentPane();

      // JTable table = createTable();
      contentPane.setLayout(new BorderLayout());
      contentPane.add(comp);

      shell.open();
      while (!shell.isDisposed()) {
      if (!display.readAndDispatch())
      display.sleep();
      }
      display.dispose();
      System.exit(0);
      }

      /**
      * @return
      */
      private static Component createComponent() {
      return new JPanel() {
      protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.fillOval(0, 0, getWidth(), getHeight());
      // g.fillOval(0, 0, getWidth(), getHeight());
      // g.fillOval(0, 0, getWidth(), getHeight());
      // g.fillOval(0, 0, getWidth(), getHeight());
      // g.fillOval(0, 0, getWidth(), getHeight());
      }
      };
      }
      }

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

      Attachments

        Activity

          People

            dav Andrei Dmitriev (Inactive)
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Imported:
              Indexed: