Graphics2D setfont()大大减慢了java应用程序的启动速度

时间:2014-07-26 13:09:10

标签: java swing fonts java-2d

大家好我是用java制作游戏,每秒刷新60次。每次执行循环时我都会使用g2d来绘制图像和字符串。如果我g2d.setFont(new Font("Arial", Font.PLAIN, 8));,事情就可以正常工作 和抽绳,这是正常的,但如果我将字体设置为某些"陌生"字体和做同样的事情,秋天将在启动的第一秒显示白色屏幕,然后正确地绘制所有内容,它显然太慢。(2秒)

我在jframe中放了一个jpanel并覆盖jpanel的paint()方法来绘制我需要的所有东西。我已经在我的代码中使用了SwingUtilities.invokeLater

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

public class Window extends JFrame{
    public Window(){
        add(new Board());
        setSize(800,600);
        setVisible(true);
    }
    public static void main(String[] args){
        new Window();
    }

    private class Board extends JPanel {
        Font font = new Font("Bitmap", Font.PLAIN, 64);

        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D)g;
            g2d.setFont(font);
            g2d.drawString("This is slow", 220,200);
            Toolkit.getDefaultToolkit().sync();
            g2d.dispose();
            g.dispose();
        }
    }
}

这不是一个循环,但它非常滞后。

http://fontsov.com/download-fonts/bitmap1159.html

这是可以减慢我们的应用程序速度的可爱字体。 " Arial字体"将加载速度极快。我怎样才能减少这种迟钝?

2 个答案:

答案 0 :(得分:5)

首先,为了获得最佳帮助,请创建并发布您的minimal code example program,以供我们审核,测试和修复。没有这个,我们就很难完全理解你的问题。

考虑:

  • 覆盖paintComponent而不是paint以获得双缓冲的优势。
  • 避免使用invokeLater,除非您确定从Swing事件线程中调用代码并且您正在进行需要在事件线程上进行的调用。
  • 将慢速运行的代码放在后台线程中,例如可以使用SwingWorker找到的线程。
  • 将文本放在JLabel中,而不是在组件上绘制。
  • 将所有静态图像绘制到BufferedImage,并在paintComponent中显示。然后直接在paintComponent方法中绘制所有变化的图像,例如移动的精灵。
  • 请勿忘记在super.paintCompmonent(g)方法覆盖范围内致电paintComponent(Graphics g)

修改
BufferedImage解决方案看起来像......,

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.*;
import java.awt.image.BufferedImage;

import javax.swing.*;

public class FooFun {

   private static void createAndShowGui() {
      ChildClass mainPanel = new ChildClass();

      JFrame frame = new JFrame("FooFun");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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

abstract class FirstClass extends JPanel {

   private static final int FPS = 20;

   public FirstClass() {
      new Timer(1000 / FPS, taskPerformer).start();
   }

   ActionListener taskPerformer = new ActionListener() {
      public void actionPerformed(ActionEvent e) {
          gameLoop(); //do loop here
          repaint();
      }
  };

  private void gameLoop() {

  }

  @Override
protected void paintComponent(Graphics g) {
   super.paintComponent(g);
   Graphics2D g2d = (Graphics2D)g;
   paintGame(g2d);
   // Toolkit.getDefaultToolkit().sync();
   // g2d.dispose();
   // g.dispose();
}

  public abstract void paintGame(Graphics2D g2d);
}

class ChildClass extends FirstClass {
   private static final Font font = new Font("Bitmap", Font.PLAIN, 64);
   private static final int PREF_W = 900;
   private static final int PREF_H = 600;
   private static final String NIGHT_IN_VEGAS_TEXT = "a Night in Vegas";
   private static final int NIV_X = 240;
   private static final int NIV_Y = 130;
   private BufferedImage mainImage;

   public ChildClass() {
      mainImage = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB);
      Graphics2D g2 = mainImage.createGraphics();
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
      g2.setFont(font);
      g2.setColor(Color.black);
      g2.drawString(NIGHT_IN_VEGAS_TEXT, NIV_X, NIV_Y); 
      g2.dispose();
   }


   @Override
   public void paintGame(Graphics2D g2d) {
      if (mainImage != null) {
         g2d.drawImage(mainImage, 0, 0, this);     
      }
   }

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

}

编辑2
或者使用SwingWorker后台线程....

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.concurrent.ExecutionException;

import javax.swing.*;

public class FooFun {

   private static void createAndShowGui() {
      ChildClass mainPanel = new ChildClass();

      JFrame frame = new JFrame("FooFun");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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

abstract class FirstClass extends JPanel {

   private static final int FPS = 20;

   public FirstClass() {
      new Timer(1000 / FPS, taskPerformer).start();
   }

   ActionListener taskPerformer = new ActionListener() {
      public void actionPerformed(ActionEvent e) {
         gameLoop(); // do loop here
         repaint();
      }
   };

   private void gameLoop() {

   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2d = (Graphics2D) g;
      paintGame(g2d);
   }

   public abstract void paintGame(Graphics2D g2d);
}

class ChildClass extends FirstClass {
   private static final Font font = new Font("Bitmap", Font.PLAIN, 64);
   private static final int PREF_W = 900;
   private static final int PREF_H = 600;
   private static final String NIGHT_IN_VEGAS_TEXT = "a Night in Vegas";
   private static final int NIV_X = 240;
   private static final int NIV_Y = 130;
   private BufferedImage mainImage;

   public ChildClass() {
      imgWorker.addPropertyChangeListener(new ImgWorkerListener());
      imgWorker.execute();
   }

   private class ImgWorkerListener implements PropertyChangeListener {

      @Override
      public void propertyChange(PropertyChangeEvent pcEvt) {
         if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) {
            try {
               mainImage = imgWorker.get();
               // repaint() here if you don't have a game loop running
            } catch (InterruptedException | ExecutionException e) {
               e.printStackTrace();
            }
         }
      }
   }

   SwingWorker<BufferedImage, Void> imgWorker = new SwingWorker<BufferedImage, Void>() {

      @Override
      protected BufferedImage doInBackground() throws Exception {
         BufferedImage img = new BufferedImage(PREF_W, PREF_H,
               BufferedImage.TYPE_INT_ARGB);
         Graphics2D g2 = img.createGraphics();
         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);
         g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
               RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
         g2.setFont(font);
         g2.setColor(Color.black);
         g2.drawString(NIGHT_IN_VEGAS_TEXT, NIV_X, NIV_Y);
         g2.dispose();
         return img;
      }
   };

   @Override
   public void paintGame(Graphics2D g2d) {
      if (mainImage != null) {
         g2d.drawImage(mainImage, 0, 0, this);
      }
   }

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

}

答案 1 :(得分:1)

每次调用paint()时都会创建一个新的Font有点不经济(这会发生很多),你可以将它移到你的构造函数中。 并且字体应该更改为一些正统字体(Arial,Calibri等)