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

标签 java swing fonts java-2d

我正在用 java 制作游戏,它每秒刷新 60 次。每次它执行一个循环,我使用 g2d 绘制图像和字符串。如果我执行 g2d.setFont(new Font("Arial", Font.PLAIN, 8)); 和 drawstring 一切正常,但如果我将字体设置为一些“不熟悉的” "字体并做同样的事情, 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();
        }
    }
}

这不是在循环中,但它非常滞后。

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

这是使我们的应用程序变慢的可爱字体。 “Arial”加载速度极快。我怎样才能减少这种延迟?

最佳答案

首先,为了获得最佳帮助,请创建并发布您的 minimal code example program供我们审查、测试并可能修复。否则,我们将很难完全理解您的问题。

考虑:

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

}

关于java - Graphics2D setfont() 严重减慢了 java 应用程序的启动速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24971336/

相关文章:

java - 身份验证后回调时出现404错误(Spring Boot + Angular + Okta)

java - 将 ResultSet 添加到 Jtable 中(两个类之间)

html - 在 css 中使用 ttf 文件

java - Jackson - 使用 treeToValue 时处理 Json 节点中的文本?

java - 可靠的 Java 声音 API,用于简单的数字样本回放

java - 保存文件/打开文件对话框,使用 Swing 和 Netbeans GUI 编辑器

java - 如何在 Java Swing 应用程序中管理来自 Controller 的 View 更新

html - 在 Microsoft Edge 中使用@font-face

c# - 在另一个 WinForms 对话框中嵌入 FontDialog

java - Collections.sort() throws 比较方法违反了它的一般约定!异常(exception)