大家好我是用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字体"将加载速度极快。我怎样才能减少这种迟钝?
答案 0 :(得分:5)
首先,为了获得最佳帮助,请创建并发布您的minimal code example program,以供我们审核,测试和修复。没有这个,我们就很难完全理解你的问题。
考虑:
paintComponent
而不是paint
以获得双缓冲的优势。invokeLater
,除非您确定从Swing事件线程中调用代码并且您正在进行需要在事件线程上进行的调用。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等)