我正在用java制作一个游戏,它每秒刷新60次。每次它执行一个循环时,我都使用g2d绘制图像和字符串。如果我执行g2d.setFont(new Font("Arial", Font.PLAIN, 8));
和绘图字符串,一切都很正常,但如果我将字体设置为“不熟悉”的字体并执行相同的操作,swing将在启动的第一秒显示白色屏幕,然后正确地绘制所有内容,而且它显然太慢了(2秒)。
我在jframe中放置了一个jpanel,并覆盖jpanel的画图()方法来绘制我需要的所有东西。我已经在代码中使用了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“将以惊人的速度加载。我怎么才能让这个不那么滞后呢?
发布于 2014-07-26 13:14:28
首先,为了获得最好的帮助,创建并发布您的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);
}
}
发布于 2014-07-26 13:22:32
每次调用each ()时创建一个新字体有点不经济(这种情况经常发生),您可以将它移到构造函数中。字体应该改为一些正统型字体(Arial,杯标等)。
https://stackoverflow.com/questions/24971336
复制相似问题