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

Graphics2D setfont()大大降低了java应用程序的启动速度,java,swing,fonts,java-2d,Java,Swing,Fonts,Java 2d,我正在用java制作一个游戏,它每秒刷新60次。每次它执行一个循环,我使用g2d来绘制图像和字符串。如果我使用g2d.setFont(新字体(“Arial”,Font.PLAIN,8)),一切都正常和抽绳,这是正常的,但如果我将字体设置为一些“不熟悉”的字体并执行相同的操作,swing将在启动的第一秒钟显示白色屏幕,然后正确地绘制所有内容,速度显然太慢(2秒) 我将一个jpanel放在jframe中,并重写jpanel的paint()方法来绘制所需的所有内容。我已经在代码中使用了SwingUti

我正在用java制作一个游戏,它每秒刷新60次。每次它执行一个循环,我使用g2d来绘制图像和字符串。如果我使用
g2d.setFont(新字体(“Arial”,Font.PLAIN,8)),一切都正常和抽绳,这是正常的,但如果我将字体设置为一些“不熟悉”的字体并执行相同的操作,swing将在启动的第一秒钟显示白色屏幕,然后正确地绘制所有内容,速度显然太慢(2秒)

我将一个jpanel放在jframe中,并重写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();
        }
    }
}
这不是一个循环,但它非常滞后


这是可爱的字体,减慢了我们的应用程序。“Arial”将以极快的速度加载。我怎样才能让这篇文章不那么冗长?

首先,为了获得最佳帮助,请创建并发布您的文章,供我们审阅、测试和可能的修复。没有这一点,我们将很难完全理解您的问题

考虑:

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

编辑
BuffereImage解决方案可能看起来像

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);
   }

}
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Font;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.RenderingHints;
导入java.awt.event.*;
导入java.awt.image.buffereImage;
导入java.beans.PropertyChangeEvent;
导入java.beans.PropertyChangeListener;
导入java.util.concurrent.ExecutionException;
导入javax.swing.*;
公共课美食坊{
私有静态void createAndShowGui(){
ChildClass主面板=新的ChildClass();
JFrame=新JFrame(“FooFun”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(主面板);
frame.pack();
frame.setLocationByPlatform(真);
frame.setVisible(true);
}
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
createAndShowGui();
}
});
}
}
抽象类FirstClass扩展了JPanel{
专用静态最终整数FPS=20;
公共头等舱(){
新计时器(1000/FPS,taskPerformer).start();
}
ActionListener taskPerformer=新建ActionListener(){
已执行的公共无效操作(操作事件e){
gameLoop();//在此处执行循环
重新油漆();
}
};
私有void gameLoop(){
}
@凌驾
受保护组件(图形g){
超级组件(g);
Graphics2D g2d=(Graphics2D)g;
绘画游戏(g2d);
}
公共抽象虚空绘画游戏(Graphics2D g2d);
}
类ChildClass扩展了第一类{
私有静态最终字体字体=新字体(“位图”,Font.PLAIN,64);
专用静态最终整型预调W=900;
专用静态最终整型参数参数H=600;
私有静态最终字符串NIGHT_IN_VEGAS_TEXT=“a NIGHT IN VEGAS”;
专用静态最终int NIV_X=240;
私有静态最终整数NIV_Y=130;
私有缓冲区映像主映像;
公共儿童班(){
addPropertyChangeListener(新的ImgWorkerListener());
imgWorker.execute();
}
私有类ImgWorkerListener实现PropertyChangeListener{
@凌驾
公共作废属性更改(属性更改事件pcEvt){
if(pcEvt.getNewValue()==SwingWorker.StateValue.DONE){
试一试{
mainImage=imgWorker.get();
//如果没有运行游戏循环,请在此处重新绘制()
}捕获(中断异常|执行异常e){
e、 printStackTrace();
}
}
}
}
SwingWorker imgWorker=新SwingWorker(){
@凌驾
受保护的BuffereImage doInBackground()引发异常{
BuffereImage img=新的BuffereImage(预镜像,预镜像,
BuffereImage.TYPE_INT_ARGB);
Graphics2D g2=img.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_抗锯齿,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY\u TEXT\u抗锯齿,
RenderingHints.VALUE\u TEXT\u ANTIALIAS\u ON);
g2.setFont(字体);
g2.设置颜色(颜色为黑色);
g2.抽绳(文本中的NIGHT_,NIV_X,NIV_Y);
g2.dispose();
返回img;
}
};
@凌驾
公共虚空绘画游戏(Graphics2D g2d){
如果(mainImage!=null){
g2d.drawImage(mainImage,0,0,this);
}
}
@凌驾
公共维度getPreferredSize(){
返回新维度(PREF_W,PREF_H);
}
}

每次调用paint()时创建一种新字体有点不经济(这种情况经常发生),您可以将其移动到构造函数中。
而且字体应该改为一些正统字体(Arial、Calibri等)

在不设置
新字体的情况下尝试。将字体缓存为类成员,并使用该字体。看看是否有不同的结果。除此之外,请为我们发布一个测试setar的字体数