绘制多个实例后,JPanel 绘图速度变慢
JPanel drawing is slowed down after several instances are painted
我正在构建游戏并使用 JPanel 的绘制功能绘制道路精灵。可以通过拖动鼠标来建造道路(建筑物 class),并且在每个字段上都会出现一个新的道路精灵。但是在我画了大约 20 个道路精灵之后,绘图变得非常慢。
我有一个框架,上面有这个 JPanel。
这是我的游戏绘图所在的 JPanel 的代码:
private class GamePanel extends JPanel implements ActionListener{
Field[][] map = gameEngine.getMap().getFields();
ArrayList<Building> buildings = gameEngine.getBuildings();
Timer timer;
ArrayList<Field> fields = new ArrayList<>();
GameFrame frame; //REFERENCE FOR THE CONTAINER OF THIS PANEL
private int mousePosX;
private int mousePosY;
GamePanel(GameFrame frame){
/*...*/
Mouse mouseListener = new Mouse();
addMouseListener(mouseListener);
addMouseMotionListener(mouseListener);
timer = new Timer(1000/30,this);
timer.start();
/*...*/
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public void draw(Graphics g){
for(Building b : buildings){
int drawPosX = b.getLocation().getPos().x*40;
int drawPosY = b.getLocation().getPos().y*40;
try {
BufferedImage img = ImageIO.read(new File("src/GFX/" + b.getType() + ".png"));
g.drawImage(img, drawPosX, drawPosY, null);
} catch (IOException e) {
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
// I thought this is not needed because I call "repaint()" only at mouse events (like
// building road by dragging)
}
public class Mouse extends MouseAdapter{
@Override
public void mouseDragged(MouseEvent evt){
repaint(); // THIS IS AN EXAMPLE TO WHERE I CALL THE REPAINT()
fieldPosX = evt.getX() - (evt.getX() % 40);
fieldPosY = evt.getY() - (evt.getY() % 40);
gameEngine.placeRoad(new SimpleRoad(new Field(fieldPosX/40,fieldPosY/40)));
}
/*... OTHER MOUSE EVENTS ...*/
}
我认为仅在鼠标事件时调用 repaint() 会优化速度,但事实并非如此。我附上了一张GIF,可以看到经过2条路,速度真的很慢。
我听说过 invokeLater,人们建议我使用它,但我不知道如何在这个项目中实现它。为什么我的游戏在几个建筑之后变慢了,我在哪里犯了错误? invokeLater 会解决问题吗?如何将它放入我的项目中?
感谢您的帮助!
Why is my game getting slower after several buildings,
try
{
BufferedImage img = ImageIO.read(new File("src/GFX/" + b.getType() + ".png"));
g.drawImage(img, drawPosX, drawPosY, null);
}
画法中不要I/O。当您添加更多建筑物时,您正在做更多的事情 I/O.
应该在 class 的构造函数中读取图像。
可以将它们保存在一个HashMap中,方便在画法中访问。
或者,图像可以保存为建筑物 class 本身的一部分。
我正在构建游戏并使用 JPanel 的绘制功能绘制道路精灵。可以通过拖动鼠标来建造道路(建筑物 class),并且在每个字段上都会出现一个新的道路精灵。但是在我画了大约 20 个道路精灵之后,绘图变得非常慢。
我有一个框架,上面有这个 JPanel。 这是我的游戏绘图所在的 JPanel 的代码:
private class GamePanel extends JPanel implements ActionListener{
Field[][] map = gameEngine.getMap().getFields();
ArrayList<Building> buildings = gameEngine.getBuildings();
Timer timer;
ArrayList<Field> fields = new ArrayList<>();
GameFrame frame; //REFERENCE FOR THE CONTAINER OF THIS PANEL
private int mousePosX;
private int mousePosY;
GamePanel(GameFrame frame){
/*...*/
Mouse mouseListener = new Mouse();
addMouseListener(mouseListener);
addMouseMotionListener(mouseListener);
timer = new Timer(1000/30,this);
timer.start();
/*...*/
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public void draw(Graphics g){
for(Building b : buildings){
int drawPosX = b.getLocation().getPos().x*40;
int drawPosY = b.getLocation().getPos().y*40;
try {
BufferedImage img = ImageIO.read(new File("src/GFX/" + b.getType() + ".png"));
g.drawImage(img, drawPosX, drawPosY, null);
} catch (IOException e) {
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
// I thought this is not needed because I call "repaint()" only at mouse events (like
// building road by dragging)
}
public class Mouse extends MouseAdapter{
@Override
public void mouseDragged(MouseEvent evt){
repaint(); // THIS IS AN EXAMPLE TO WHERE I CALL THE REPAINT()
fieldPosX = evt.getX() - (evt.getX() % 40);
fieldPosY = evt.getY() - (evt.getY() % 40);
gameEngine.placeRoad(new SimpleRoad(new Field(fieldPosX/40,fieldPosY/40)));
}
/*... OTHER MOUSE EVENTS ...*/
}
我认为仅在鼠标事件时调用 repaint() 会优化速度,但事实并非如此。我附上了一张GIF,可以看到经过2条路,速度真的很慢。
我听说过 invokeLater,人们建议我使用它,但我不知道如何在这个项目中实现它。为什么我的游戏在几个建筑之后变慢了,我在哪里犯了错误? invokeLater 会解决问题吗?如何将它放入我的项目中?
感谢您的帮助!
Why is my game getting slower after several buildings,
try
{
BufferedImage img = ImageIO.read(new File("src/GFX/" + b.getType() + ".png"));
g.drawImage(img, drawPosX, drawPosY, null);
}
画法中不要I/O。当您添加更多建筑物时,您正在做更多的事情 I/O.
应该在 class 的构造函数中读取图像。
可以将它们保存在一个HashMap中,方便在画法中访问。
或者,图像可以保存为建筑物 class 本身的一部分。