我做了一个基于Java的游戏,利用包含JApplet的JFrame,该JApplet又包含一个JPanel,在该JPanel上绘制图形,但由于某种原因,图形的左侧偶尔会闪烁,弄清楚为什么。我想这可能是因为我实际上并没有使用EDT,我之后才意识到这一点,所以有人能够告诉我如何正确地将EDT的使用整合到程序中?在JApplet中正确使用Event Dispatch Thread?
我的主类的样子:
public class Main extends JFrame{
public static final int HEIGHT = 600;
public static final int WIDTH = 800;
public static RApplet app;
public Main(){
setTitle("RCrawl");
Container c = getContentPane();
c.setPreferredSize(new Dimension(WIDTH, HEIGHT));
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setResizable(false);
final Player p = new Player(50, 70, true);
final Room r = new Room(0xff222244);
r.addEntity(new EntityRock(200, 150));
app = new RApplet(WIDTH, HEIGHT);
app.setRoom(r);
app.setPlayer(p);
app.setFps(25);
add(app);
setVisible(true);
new UpdateThread().start();
System.out.println("thread run");
}
public static void main(String[] args){
Main m = new Main();
}
class UpdateThread extends Thread{
public void run(){
while(true)update();
}
public void update(){
app.refresh();
}
}
}
虽然RApplet类的样子:
public class RApplet extends JApplet{
public int width, height, fps;
public long curTime, delta;
public RenderPanel panel;
public Room curRoom;
public Player player;
public boolean isSingle;
public InputHandler input;
public RApplet(int x, int y){
width = x;
height = y;
panel = new RenderPanel(width, height);
fps = 30;
isSingle = true;
input = new InputHandler();
addKeyListener(input);
setFocusable(true);
add(panel);
}
public void setPlayer(Player p){
player = p;
curRoom.addPlayer(p);
}
public void setFps(int f){
fps = f;
}
public void initialize(){
curTime = System.currentTimeMillis();
delta = curTime;
}
public void refresh(){
delta = (int)(System.currentTimeMillis() - curTime);
if(delta > 1000/fps){
curTime = System.currentTimeMillis();
render();
tick();
}
}
public void setRoom(Room r){
curRoom = r;
}
public void render(){
panel.renderStart(curRoom);
panel.renderRoom(curRoom);
panel.renderEnd();
panel.repaint();
}
public void tick(){
curRoom.tick(this);
}
}
所以我什么希望,才能正常使用EDT办?我已经尝试了几种使用不同组合的invokeLater()
和invokeAndWait()
,但无法让他们工作。如果你能帮助,任何帮助表示赞赏。
编辑:下面是来自RenderPanel
渲染方法:
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
BufferedImage drawer = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g1 = drawer.getGraphics();
g1.drawImage(canvas, 0, 0, this);
g2.drawImage(drawer, 0, 0, this);
g1.dispose();
g2.dispose();
}
那不是双缓冲?
'',它利用了包含JApplet的JFrame“' - 为什么这个*非常*奇怪而脆弱的设计?这不应该是一个拥有JPanel的JFrame吗? – 2015-02-08 15:12:31
在将Applet移动到网页之前,我正在使用JFrame对其进行测试。 – user2649681 2015-02-08 15:46:53
1.不要在paintComponent方法中执行BufferedImage绘图,即从'BufferedImage drawer = ....'到'g1.drawImage(...)'的所有内容。这应该在其他地方完成,可能在后台线程中。另外,尽管可以放弃BufferedImage的Graphics对象g1,但是在完成它之后,不要处置由JVM提供给您的Graphics对象,即g2对象。这将打破Swing的绘画树。 – 2015-02-08 16:16:40