为什么使用Swing绘制在Java 8和Java 6中的表现不同?

时间:2014-12-29 03:39:59

标签: java swing graphics java-8 java-6

我正在使用Swing作为GUI开发Java应用程序。在这个项目中,我使用的是Java 8 Update 25.我一直在用Java编写另一个图形应用程序,但我使用的是Java 6.在这两个项目中,我都编写了相同的paint()方法。 (如下所示)我也打电话给#re; repaint()'同样的方式。在这两个项目中,我正在绘制一个字符串。此字符串显示本地int,count的值;每次调用paint()方法时,计数都会增加一。

当两个项目表现不同时,我的问题出现了。在Java 6中,屏幕更新速度非常快,应用程序的行为也很理想。但是,在Java 7和8中,应用程序不显示任何内容。如果我增加重绘之间的延迟,(大约300毫秒)我能看到字符串闪烁。但是,如果我想用Java 8开发游戏,那么角色的闪烁和抖动是非常不可取的。

为什么不同的Java版本以这种方式表现不同?有没有一种方法可以使用类似的设置在Java 8中复制流畅的重绘(通过Java 6)? (如下所列)如果有,怎么样?如果没有,如何实现平滑,最小的闪烁显示? (我更喜欢这种重画不断重新粉饰,但它不像显示器的流程那样必要)

感谢您的帮助,  〜录音棚

Java 6项目代码:

public class App {

static AppDisplay display = new AppDisplay();

  public static void main(String args[]) {

    display.setup();

    Thread graphics = new Thread() {
      public void run() {
        while(true) {
          display.repaint();
          try {
            Thread.sleep(17); // This is the delay I am talking about above
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }
    };
    graphics.start();


  }
}

public class AppDisplay() extends JFrame {
  private static final long serialVersionUID = 1L;

  int count = 0;

  public void setup() {
    this.setSize(600, 600);
    this.setTitle("Application");
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    this.setVisible(true);
  }

  public void paint(Graphics g) {
    super.paint(g);
    g.drawString("Count: " + count);
    count ++;
  }
}

Java 8代码:

public class App {

static AppDisplay display = new AppDisplay();

  public static void main(String args[]) {

    display.setup();

    Thread graphics = new Thread() {
      public void run() {
        while(true) {
          display.repaint();
          try {
            Thread.sleep(17); // Delay
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }
    };
    graphics.start();


  }
}

public class AppDisplay() extends JFrame {
  private static final long serialVersionUID = 1L;

  int count = 0;

  public void setup() {
    this.setSize(600, 600);
    this.setTitle("Application");
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    this.setVisible(true);
  }

  public void paint(Graphics g) {
    super.paint(g);
    g.drawString("Count: " + count);
    count ++;
  }
}

1 个答案:

答案 0 :(得分:5)

  • 永远不要直接在JFrame中绘制。
  • 始终绘制JComponent,例如JPanel或JComponent。
  • 并使用paintComponent(Graphics g)覆盖,而不是paint(Graphics g)覆盖,以获得自动双缓冲的好处。
  • 请不要发布草率代码。如果您的类扩展了另一个类,请显示它。细节很重要。

如,

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class MyApp extends JPanel {

   private static final int PREF_W = 600;
   private static final int PREF_H = 400;
   private static final int DELAY = 17;
   private int count = 0;

   public MyApp() {
      new Timer(DELAY, new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent e) {
            count++;
            repaint();
         }
      }).start();
   }

   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.drawString("Count = " + count, 20, 20);
   }

   private static void createAndShowGUI() {
      MyApp paintEg = new MyApp();

      JFrame frame = new JFrame("MyApp");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(paintEg);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGUI();
         }
      });
   }
}