开发者

Java slow 2D performance - Resizing

开发者 https://www.devze.com 2023-03-28 09:22 出处:网络
I am using Windows 7 with Aero, and have a very fast graphics card (Radeon 6870) that I use for gaming.

I am using Windows 7 with Aero, and have a very fast graphics card (Radeon 6870) that I use for gaming.

I have some issues when resizing very simple programs I make with java. For instance, this program does absolutely nothing. It has no action listeners, no loops. It's simply a GUI interface with buttons.

Resizing with OpenGL acceleration off:

[View fullscreen]

Java slow 2D performance - Resizing

It takes about a second to resize the components. For me that's very noticeable.

Resizing with OpenGL acceleration on:

Java slow 2D performance - Resizing

I have tried to enable OpenGl acceleration to solve this problem. I compiled the JAR and run it with java -Dsun.java2d.opengl=true -jar C:\Test.jar. The result is slightly less black areas around the window, but much more flickering. In fact the flickering shows up as grey in the screenshot above.

Is the issue present in any other software?

No. Eclipse, Netbeans, Chrome and other applications have been tested. None have this issue. Therfore I must conclude that there must be some problem with the code. Various people have run this code and said they have "No issues". If you are going to test it, please make sure you resize the window from the smallest size to the largest size of the screen, whilst moving the mouse in circular motion.

Code:

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

public class JFrameWithButtonsTest {
    private int iScreen = 25;  
    private int iLocation = 10;
    JFrame frame = new JFrame();
    Container contentPane = frame.getContentPane();

    public JFrameWithButtonsTest() {
        JPanel northButtonPanel = new JPanel();
        northButtonPanel.setLayout(new GridLayout(2,2));
        northButtonPanel.add(new JButton(" I do nothing"));
        northButtonPanel.add(new JButton(" I do nothing"));
        northButtonPanel.add(new JButton(" I do nothing"));
        northButtonPanel.add(new JButton(" I do nothing"));
        contentPane.add(northButtonPanel, BorderLayout.NORTH);

        JPanel southButtonPanel = new JPanel();
        southButtonPanel.setLayout(new GridLayout(2,2));
        southButtonPanel.add(new JButton(" I do nothing"));
        southButtonPanel.add(new JButton(" I do nothing"));
        southButtonPanel.add(new JButton(" I do nothing"));
        southButtonPanel.add(new JButton(" I do nothing"));
        contentPane.add(southButtonPanel, BorderLayout.SOUTH);

        JPanel eastButtonPanel = new JPanel();
        eastButtonPanel.setLayout(new GridLayout(2,2));
        开发者_Python百科eastButtonPanel.add(new JButton(" I do nothing"));
        eastButtonPanel.add(new JButton(" I do nothing"));
        eastButtonPanel.add(new JButton(" I do nothing"));
        eastButtonPanel.add(new JButton(" I do nothing"));
        contentPane.add(eastButtonPanel, BorderLayout.EAST);

        boolean packFrame = false;
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension frameSize = frame.getSize();
        frameSize.height = (int) (iScreen * screenSize.height / 100);
        frameSize.width = (int) (iScreen * screenSize.width / 100);
        frame.setSize(frameSize);
        frame.setLocation((screenSize.width - frameSize.width) / iLocation,
                (screenSize.height - frameSize.height) / iLocation);
        if (packFrame) {
            frame.pack();
            packFrame = true;
        } else {
            frame.validate();
        }
        frame.setVisible(true);
    }
    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            e.printStackTrace();
        }
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new JFrameWithButtonsTest();
            }
        });
    }
}

Note that the issue is still present without this line: UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());


I started to notice that for two of my recent Java programs.

I had a look at NetBeans' configuration file, and found the following would improve the situation a lot:

  public static void main(final String... args) {
    System.setProperty("sun.java2d.noddraw", Boolean.TRUE.toString());
    ...

Which is the same as -Dsun.java2d.noddraw=true on the JVM command line.


This trick improves repaint rate in Win7+Aero: setting resizable to null, and providing own resize hook. Its aint perfect, but still alot better.. check my example:

http://i.stack.imgur.com/IrPAb.png

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

class ResizeHookDemo extends JDialog {
  private final static int width = 580, height = 350;
  private final JFileChooser fc;
  private java.awt.geom.GeneralPath gp;

  public ResizeHookDemo() {
    super((JDialog)null, "Choose File", true);

    fc = new JFileChooser() {

     @Override
     public void paint(Graphics g) {
       super.paint(g);
       int w = getWidth();
       int h = getHeight();
       g.setColor(new Color(150, 150, 150, 200));
       g.drawLine(w-7, h, w, h-7);
       g.drawLine(w-11, h, w, h-11);
       g.drawLine(w-15, h, w, h-15);

       gp = new java.awt.geom.GeneralPath();      
       gp.moveTo(w-17, h);
       gp.lineTo(w, h-17);
       gp.lineTo(w, h);
       gp.closePath();
     }

    };
    fc.addActionListener(new ActionListener() {

      public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("CancelSelection")) {
          setVisible(false);
          // action...
        }
        else if (e.getActionCommand().equals("ApproveSelection")) {
          setVisible(false);
          // action...
        }
      }
    });

    MouseInputListener resizeHook = new MouseInputAdapter() {
      private Point startPos = null;

      public void mousePressed(MouseEvent e) {
        if (gp.contains(e.getPoint())) 
          startPos = new Point(getWidth()-e.getX(), getHeight()-e.getY());
      }

      public void mouseReleased(MouseEvent mouseEvent) {
        startPos = null;
      }

      public void mouseMoved(MouseEvent e) {
        if (gp.contains(e.getPoint()))
          setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
        else
          setCursor(Cursor.getDefaultCursor());
      }

      public void mouseDragged(MouseEvent e) {
        if (startPos != null) {

          int dx = e.getX() + startPos.x;
          int dy = e.getY() + startPos.y;

          setSize(dx, dy);
          repaint();
        }
      }         
    };

    fc.addMouseMotionListener(resizeHook);
    fc.addMouseListener(resizeHook);
    fc.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 20));
    add(fc);

    setResizable(false);

    setMinimumSize(new Dimension(width, height));
    setDefaultCloseOperation(HIDE_ON_CLOSE);
    setLocationRelativeTo(null);
  }

  public static void main(String args[]) {
    System.out.println("Starting demo...");
    SwingUtilities.invokeLater(new Runnable() {

      @Override
      public void run() {
        new ResizeHookDemo().setVisible(true);
      }
    });
  }
}


If you are running it on Win 7 with Aero, it is known problem:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6898838
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6873928


Usually Flickering can be improved if not solved using double buffering, you can enable it by setting true to each of the panels .setDoubleBuffer(true);

To read more about it : http://download.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html

0

精彩评论

暂无评论...
验证码 换一张
取 消