我正在用 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/