如何解决 Java awt/swing 图像打印的滞后问题?
Posted
技术标签:
【中文标题】如何解决 Java awt/swing 图像打印的滞后问题?【英文标题】:How do you solve lagging in Java awt/swing image printing? 【发布时间】:2018-05-23 13:09:52 【问题描述】:我正在尝试使用 Java swing/awt 制作一个简单的游戏。 在屏幕上打印和移动图像时出现滞后问题。
下面是我的代码:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.File;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.*;
public class StarDef extends JFrame implements Runnable, KeyListener
private BufferedImage back;
private boolean start = false, end = false;
public int w = 1500, h = 800, commandx = 200, commandy = 100, ground = 500, mineral = 100;
private int mineralx = 0, mineraly = commandy + 104;
private int dronecnt = 0;
private ArrayList<Drone> DrList = null;
private ArrayList<Enemy> EnList = null;
private ArrayList<Building> BuildList = null;
private ArrayList<Allies> AlyList= null;
public Image imagearr[] = new Image[10];
private boolean makedrone = false, NeedMinerals = false;
public int picnum = 1;
private int OrderBuild = 0;
public static void main(String[] args)
Thread t = new Thread(new StarDef());
t.start();
public StarDef()
back = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
DrList = new ArrayList<>();
BuildList = new ArrayList<>();
EnList = new ArrayList<>();
AlyList = new ArrayList<>();
this.addKeyListener(this);
this.setSize(w,h);
this.setTitle("Starcraft");
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
try
imagearr[0] = ImageIO.read(new File("Char/Command.png"));
imagearr[1] = ImageIO.read(new File("Char/droneleft.png"));
imagearr[2] = ImageIO.read(new File("Char/droneright.png"));
imagearr[3] = ImageIO.read(new File("Char/Mineral.png"));
imagearr[4] = ImageIO.read(new File("Char/barracks.png"));
catch (Exception e)
e.printStackTrace();
public void initGame()
DrList.clear();
mineral = 100;
public void draw()
Graphics gs = back.getGraphics();
gs.setColor(Color.white);
gs.fillRect(0,0,w,h);
gs.setColor(Color.DARK_GRAY);
gs.fillRect(0,ground,w,200);
if (!end)
gs.drawImage(imagearr[0], commandx, commandy, null); // First Image-Command Center
gs.drawImage(imagearr[3], mineralx,mineraly,null); // Second Image-Mineral
for (int i = 0; i < DrList.size(); i++) //Printing Drones
Drone m = DrList.get(i);
gs.drawImage(imagearr[m.state], m.x, m.y, null); //Drawing Drones
m.moveDr(); // Moving the Drone
for (int i = 0; i < BuildList.size(); i++) //Printing Building
Building bd = BuildList.get(i);
if(bd.buildingtype == 'R')
gs.drawImage(imagearr[4], bd.x, bd.y, null); // Drawing Building-Problem starts..?
gs.drawImage(imagearr[0], commandx, commandy, null);
gs.setColor(Color.black);
gs.drawString("mineral : " + mineral, 10,50);
gs.drawString("Drones : " + DrList.size(), 10, 70);
Graphics ge = this.getGraphics();
ge.drawImage(back, 0,0,w,h,this);
public void run()
try
int timer = 10;
while (true)
Thread.sleep(timer);
if(start)
if (makedrone)
makedrone();
if (OrderBuild>0)
makeBuilding(OrderBuild);
draw();
catch (Exception e)
e.printStackTrace();
public void makeBuilding(int buildingnumber)
int bdx, bdy;
char BuildingType;
if(buildingnumber == 1)
bdx = 500;
bdy = 100;
BuildingType = 'R';
Building barracks = new Building(this, bdx, bdy, BuildingType);
BuildList.add(barracks);
public void makedrone()
if (mineral >= 50)
int dronex = commandx;
int droney = commandy+129;
Drone dr = new Drone(this ,dronex, droney);
DrList.add(dr);
dronecnt++;
mineral -= 50;
makedrone = false;
else if (mineral < 50)
NeedMinerals = true;
makedrone = false;
public void keyPressed(KeyEvent ke)
switch (ke.getKeyCode())
case KeyEvent.VK_ENTER:
start = true;
end = false;
break;
case KeyEvent.VK_D:
makedrone = true;
break;
case KeyEvent.VK_R:
OrderBuild = 1;
break;
public void keyReleased(KeyEvent ke)
switch ((ke.getKeyCode()))
public void keyTyped(KeyEvent ke)
编译代码时,前几张静止图像看起来不错。
在移动图像(无人机)很好地出现后,但当你召唤下一个静止图像(建筑物)时,开始出现严重滞后,移动无人机的速度明显降低。
建筑大约300*150像素,无人机40*30像素。
这个问题的原因是什么?是因为代码(调用图片的方式),还是图片的大小,还是电脑(我用的是笔记本(LG Gram 14in))?
【问题讨论】:
1) 为自包含示例获取图像的一种方法是热链接到在this Q&A 中看到的图像。 2) 请参阅Detection/fix for the hanging close bracket of a code block 了解我无法再费心修复的问题。 【参考方案1】:首先不要使用Graphics ge = this.getGraphics();
。
因为您还使用自己的Thread
,所以您面临线程竞争条件的风险,这可能导致脏读/绘制。
首先了解 Swing 绘画的实际工作原理以及在 API 功能中的工作原理。
首先查看Performing Custom Painting、Painting in AWT and Swing 和Concurrency in Swing
KeyListener
也是监控键输入的糟糕选择,您应该使用 Key Bindings API - 有关详细信息,请参阅How to use key bindings。
向ArrayList
添加内容会导致ArrayList
经历一个增长周期,这会消耗时间并强制延长GC 周期。考虑用初始容量播种ArrayList
,这将有助于减少生长周期之间的间隔。
专注于将“更新”逻辑与“绘制”逻辑分开,它可以帮助您发现性能问题
你也可以看看
java what is heavier: Canvas or paintComponent()? Swing animation running extremely slow Rotating multiple images causing flickering. Java Graphics2D这展示了在 Swing 中提高渲染性能的大量技术。
如果这些仍然无法让您达到您想要的水平,那么您将需要使用 BufferStrategy
进行探索
【讨论】:
以上是关于如何解决 Java awt/swing 图像打印的滞后问题?的主要内容,如果未能解决你的问题,请参考以下文章
java awt;java applet;java swing分别是啥?他们之间有啥联系和区别?