2012-11-05 115 views
1

我目前正在開發一款遊戲,它需要在JPanel(或其他容器)上繪製類似網格的地圖。 爲了在合理的時間內實現此目的並保持我的UI響應,我將容器的圖形對象 傳遞給SwingWorker子類的地圖渲染器。然後我調用啓動地圖實際繪製的地圖渲染器的執行方法。繪圖完成後,將打印一條消息。所有這些都是在我按下M鍵時開始的。Java在SwingWorker中渲染遊戲地圖無法正常工作

實際問題是僅在第一次繪製地圖時才成功。當我反覆按下M鍵時,我從來沒有收到過任何其他消息。另外,當我ALT-TAB離開我的應用程序(以全屏獨佔模式運行)並返回時,我的地圖不再可見。

我懷疑問題在於不直接在EDT線程中繪製或者沒有正確傳遞我的地圖渲染器已準備就緒。

這是我的地圖渲染器類:

public class MapRenderer extends SwingWorker<Void, Void> { 

private Graphics2D g; 
private WorldMap map; 
private int x, y, w, h, l; 


@Override 
protected Void doInBackground() throws Exception { 
    drawMap(); 
    return null; 
} 

@Override 
protected void done() { 
    super.done(); 
    System.out.println("Done"); 
} 

private void drawMap() { 
    int rw = w + 1; 
    int rh = h + 1; 

    if (rw >= map.getSize()) 
     rw = map.getSize(); 
    if (rh >= map.getSize()) 
     rh = map.getSize(); 

    for (int i = 0; i < rw; i++) { 
     for (int j = 0; j < rh; j++) { 
      g.setColor(map.getTiles()[x + i][y + j].getColor()); 
      g.fillRect(i * l, j * l, l, l); 
      if (l > 2) { 
       g.setColor(Color.DARK_GRAY); 
       g.drawRect(i * l, j * l, l, l); 
      } 
     } 
    } 
} 

public void setGraphics(Graphics2D g) { 
    this.g = g; 
} 

public void setMap(WorldMap map) { 
    this.map = map; 
} 

public void setViewPoint(Rectangle viewPoint, int squareSize) { 
    this.x = (int) viewPoint.getX(); 
    this.y = (int) viewPoint.getY(); 
    this.w = (int) viewPoint.getWidth(); 
    this.h = (int) viewPoint.getHeight(); 
    this.l = squareSize; 
} 
    } 

這就是execute()方法被調用:

private void initializeKeyBindings() { 
    this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("M"), "M"); 
    this.getActionMap().put("M", new AbstractAction() { 
     private static final long serialVersionUID = 1L; 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      drawMap(getGraphics()); 
     } 
    }); 
} 

public void drawMap(Graphics g) { 
    mapRenderer.setGraphics((Graphics2D) g); 
    mapRenderer.setViewPoint(new Rectangle(0, 0, 1600/4, 900/4), 4); 
    mapRenderer.execute(); 
} 

我對任何草率的編碼道歉,我保證我會清理在將來。

回答

1

實現SwingWorker的類的一個實例只能運行一次。所以,每次執行代碼時都應該創建一個新實例。從您提供的代碼中,它看起來好像您正在使用相同的實例。因此它會在第一時間工作,但不會連續呼叫:

public void drawMap(Graphics g) { 
    mapRenderer.setGraphics((Graphics2D) g); 
    mapRenderer.setViewPoint(new Rectangle(0, 0, 1600/4, 900/4), 4); 
    mapRenderer.execute(); 
}