我做了一個基於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