java基礎 --- Graphics

java學習第十週總結 --- Graphics

下週就開始做遊戲項目了。這周主要是對做遊戲中需要用到的知識和要點進行學習。雖然遊戲項目還未正式啓動,但是之前的準備還是要做的。將從四個部分來對所要使用到的知識點進行總結。
首先從繪圖類Graphics開始進行總結。在java的基礎類庫中,提供了專門繪圖的類Graphics和他的子類Graphics2D。這兩個類都是抽象類,因此不允許實例化。一般都是通過容器的paint方法來調用。至於如何調用我們不需要關心,我們只需要在paint方法中使用該畫筆繪圖就行了。

Graphics和Graphics2D
一般繪圖我們使用Graphics這個類來進行,但是有時候他並不能滿足我們的需要。由於這個類所繪製出的圖形不能消除鋸齒,比如象畫圓、曲線等等,或者需要對繪圖進行一些高級處理,這個時候我們就應該使用Graphics2D,這個類除類擁有Graphics的所有方法之外,還擴展了一些其他方法。具體請參看javaAPI.

public void paint(Graphics g){
 g.drawdrawOval(x, y, width, height)
 .
 .
 .
}

public void paint(Graphics g){
 Graphics2D g = (Graphics2D)g
 g.drawdrawOval(x, y, width, height)
 .
 .
 .
}
上面第一種就是使用Graphics進行繪圖,第二種是使用Graphics2D進行繪圖。爲了演示Graphics2D的一些特性,下面我們在窗口上繪製一個圖片,然後讓這個圖片逐漸變亮和變暗,類似於一些遊戲的開頭廣告。在這個小程序中我們將使用圖像跟蹤器MediaTracker和雙緩衝,這兩點將在後面的總結中介紹。

任意找張圖片作爲背景圖,圖片格式只能是jpg、gif、png。然後放在類路徑的根目錄下,我這裏圖片的路徑是/img/start.jpg。

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;

import javax.swing.JFrame;

public class G2DExample extends JFrame implements Runnable {

 
private Image img;
 
private int imgWidth;
 
private int imgHeight;
 
private float filter = 1;

 G2DExample() {

  img 
= Toolkit.getDefaultToolkit().getImage("img/start1.jpg");
  MediaTracker tracker 
= new MediaTracker(this);
  tracker.addImage(img, 
0);
  
try
  {
   tracker.waitForID(
0);
  }
  
catch (InterruptedException e)
  {
   e.printStackTrace();
  }
  imgWidth 
= img.getWidth(this);
  imgHeight 
= img.getHeight(this);
  setSize(imgWidth, imgHeight);
  setVisible(
true);
  Thread thread 
= new Thread(this);
  thread.start();
 }

 
public void paint(Graphics g) {

  Graphics2D g2 
= (Graphics2D) g;
  Image bufferImg 
= this.createImage(imgWidth, imgHeight);
  Graphics2D bufferGraphics 
= (Graphics2D) bufferImg.getGraphics();
  bufferGraphics.drawImage(img, 
00this);
  bufferGraphics.setPaint(Color.BLACK);
  bufferGraphics.setComposite(AlphaComposite.getInstance(
    AlphaComposite.SRC_OVER, filter));
  bufferGraphics.fillRect(
00, imgWidth, imgHeight);

  g2.drawImage(bufferImg, 
00this);
 }

 
public static void main(String [] args) {

  
new G2DExample();
 }

 
public void run() {

  
while (true)
  {
   
for (int i = 10; i >= 0; i--)
   {
    filter 
= (float) i / 10;
    
try
    {
     Thread.sleep(
50);
    }
    
catch (InterruptedException e)
    {
     e.printStackTrace();
    }
    repaint();
   }

   
for (int i = 0; i <= 10; i++)
   {
    filter 
= (float) i / 10;
    
try
    {
     Thread.sleep(
50);
    }
    
catch (InterruptedException e)
    {
     e.printStackTrace();
    }
    repaint();
   }

  }
 }
}

上面這個程序使用了雙緩衝技術,這個將放在後面介紹。使圖片漸變的關鍵代碼是這三句:
bufferGraphics.setPaint(Color.BLACK);
bufferGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, filter));
bufferGraphics.fillRect(0, 0, imgWidth, imgHeight);
 

bufferGraphics就是使用的是Graphics2D類,setPaint是設置矩形的顏色,setComposite就是用來設置顏色的alpha值,通過線程不斷的改變這個值,就可以達到顏色透明度的漸變。setComposite的參數是Composite,而AlphaComposite是Composite的子類,不過這個類不能通過new來創建,而需要他的一個靜態方法getInstance來創建,這個方法有兩個參數,第一個參數需要定義合成規則,具體的一些規則參看AlphaComposite介紹。第二個參數指定alpha值,最後使用fillRect填充矩形,這樣通過不停的改變第二個參數的值就可以達到圖像透明度的漸變效果。

上面這個程序是直接在JFrame上paint方法繪製圖形的,因爲JFrame並不具備雙緩衝的功能,因此需要我們顯示的使用雙緩衝來作圖,否則就會出現閃爍的情況。其實在Swing組件中,有許多輕量型組件默認就具備雙緩衝功能,而不需要我們自己去實現該功能。只要是繼承自JComponent的組件都具備雙緩衝的功能。因此這裏我們可以使用JPanel容器,在這上面繪製圖形,效果和上面的程序一樣。

G2DExampleJPanel() {

  img 
= Toolkit.getDefaultToolkit().getImage("img/start1.jpg");
  MediaTracker tracker 
= new MediaTracker(this);
  tracker.addImage(img, 
0);
  
try
  {
   tracker.waitForID(
0);
  }
  
catch (InterruptedException e)
  {
   e.printStackTrace();
  }
  imgWidth 
= img.getWidth(this);
  imgHeight 
= img.getHeight(this);
  
/*
   * 這裏創建一個繼承自JPanel類的匿名內部類,覆蓋paintComponent方法進行繪圖
   * 引用變量panel指向該對象.
   
*/
  panel 
= new JPanel() {

   
protected void paintComponent(Graphics g) {

    Graphics2D g2 
= (Graphics2D) g;
    g2.drawImage(img, 
00this);
    g2.setPaint(Color.BLACK);
    g2.setComposite(AlphaComposite.getInstance(
      AlphaComposite.SRC_OVER, filter));
    g2.fillRect(
00, imgWidth, imgHeight);

   }
  };
  
/* 將panel加在JFrame的容器面板裏面 */
  
this.getContentPane().add(panel);
  setSize(imgWidth, imgHeight);
  setVisible(
true);
  Thread thread 
= new Thread(this);
  thread.start();
 }

 
public static void main(String [] args) {

  
new G2DExampleJPanel();
 }

 
public void run() {

  
while (true)
  {
   
for (int i = 10; i >= 0; i--)
   {
    filter 
= (float) i / 10;
    
try
    {
     Thread.sleep(
50);
    }
    
catch (InterruptedException e)
    {
     e.printStackTrace();
    }
    repaint();
   }

   
for (int i = 0; i <= 10; i++)
   {
    filter 
= (float) i / 10;
    
try
    {
     Thread.sleep(
50);
    }
    
catch (InterruptedException e)
    {
     e.printStackTrace();
    }
    repaint();
   }

  }
 }
}

從效果上看在這兩個程序沒什麼區別,後一個程序是在JFrame的容器面板裏面進行圖形的繪製。這裏需要注意的是如果在JPanel或者其他繼承自JComponent的容器裏繪圖時,需要覆蓋paintComponent方法,而不是覆蓋paint方法。雖然可以這麼做,但是這並不是最好的方式。
在下一篇裏將總結遊戲中如何繪製圖片,以及解決閃爍,拖屏等問題的方案。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章