2015-08-08 32 views
2

我正在进入Java图形,我正在阅读Andrew Davison用Java编写的Killer游戏编程。他编写了一个简单的窗口应用程序,该应用程序使用Image类进行离屏渲染,然后将图像复制到组件。我感到迷惑的是,一个可以只创建图像,然后获得与图形上下文:用于屏幕外渲染的Java图形(2D)

dbg = dbImage.getGraphics(); 

我觉得很困惑,因为那时我们只使用DBG Graphics对象绘制的东西,但后来我们使用数据库图像中的paintComponent方法来显示所有我们已经吸引到DBG对象的东西:

​​3210

那么如何数据库图像“知道”,它包含了所有我们已经绘制到DBG Graphics对象的图形的东西?

这里是整个代码:

public class GamePanel extends JPanel implements Runnable{ 

    private static final int PWIDTH = 500; 
    private static final int PHEIGHT = 400; 

    private Thread animator; 

    private volatile boolean running = false; 

    private volatile boolean gameOver = false; 

    private Graphics dbg; 
    private Image dbImage = null; 

    private Counter counter; 

    public GamePanel(){ 
     setBackground(Color.white); 
     setPreferredSize(new Dimension(PWIDTH, PHEIGHT)); 

     // create game components eg. counter. 
     counter = new Counter(10); 
     counter.start(); 
    } 

    private void stopGame(){ 
     running = false; 
    } 

    @Override public void addNotify(){ 
     super.addNotify(); 
     startGame(); 
    } 

    public void startGame(){ 
     if(animator == null || !running){ 
      animator = new Thread(this); 
      animator.start(); 
     } 
    } 

    @Override 
    public void run() { 
     running = true; 
     while(running){ 
      gameUpdate(); 
      gameRender(); 
      repaint(); 
      try{ 
       Thread.sleep(20); 
      } 
      catch(InterruptedException ex){ 
       // do something with the exception... 
      } 
     } 
    } 

    private void gameUpdate(){ 
     if(!gameOver){ 
      // update game state... 
      if(counter.getCounter() == 0) 
       gameOver = true; 

     } 
    } 

    private void gameRender(){ 
     if(dbImage == null){ 
      dbImage = createImage(PWIDTH, PHEIGHT); 
      if(dbImage == null){ 
       System.out.println("dbImage is null"); 
       return; 
      }  
      else 
       dbg = dbImage.getGraphics(); // get graphics context for drawing to off-screen images. 
     } 

     // clear the background 
     dbg.setColor(Color.white); 
     dbg.fillRect(0, 0, PWIDTH, PHEIGHT); 

     // draw game elements here... 
     dbg.setColor(Color.black); 
     dbg.drawString(Integer.toString(counter.getCounter()), 10, 10); 

     if(gameOver) 
      dbg.drawString("Game over...", 10, 20); 
    } 

    @Override public void paintComponent(Graphics g){ 
     super.paintComponent(g); 
     if(dbImage != null) 
      g.drawImage(dbImage, 0, 0, null); 
    } 
} 

的重要的部分是只的paintComponent方法和gameRender()方法虽然。

+1

因为'Graphics'实例是它自己的,所以它属于图像,没有别的。简单地说:'Image'实例保持对它的引用。 (或者相反,取决于实现,但最终结果是一样的。) – biziclop

+0

所以createImage方法将dbg和dbImage绑定在一起@biziclop?它背后有一定的设计模式吗? – kimsay

回答

5

基本上,Graphics对象不是你在上画。这是你绘制

当您拨打dbImage.getGraphics()时,您的意思是“给我一个工具箱,让我借鉴这张图片”。 Graphics对象中的所有绘制方法都使用它创建的组件绘制。它们不在Graphics对象上绘制,它们绘制在属于它的ImageComponent上。

认为Graphics对象作为调色板和画笔,并在ImageComponent作为画布。

因此,当您完成dbg的运行后,这意味着您的图像中充满了彩色像素,此对象将其绘制在其上。现在,您可以拍摄该图像并将其复制到另一个组件 - 通过在该组件的Graphics中使用drawImage“工具” - 其“工具箱”。

+0

感谢您的明确回答@RealSkeptic。但是这在技术上如何工作? getGraphics方法是否以某种方式将Graphics和Image对象连接在一起? – kimsay

+2

@kismay当然是的。但具体的实现实际上取决于你所拥有的组件/图像的类型,因为像素的每个这样的“光栅”都可以以不同的方式在内存中组织像素。所以实际上'getGraphics'为你提供了一个专门为你正在使用的图像而构建的自定义对象。它恰好从'Graphics2D'继承。 – RealSkeptic