首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java ME 低階 GUI 繪圖:Canvas 與 Graphics 核心技術詳解

     編輯:Java 相關知識

在 Java ME 高階 API(如 Form、List)中,開發者無法精確控制螢幕像素級的繪製細節,系統會自動選擇最適合裝置的顯示方式。然而,遊戲或圖形密集型應用往往需要對繪圖過程有完全掌控權。MIDP javax.microedition.lcdui 套件提供的低階 API 正是為此而生,核心在於 Canvas 類別。

Canvas:繪圖的空白畫布

Canvas 繼承自 Displayable,是一個抽象類別,提供一個可自由繪製的矩形區域。要使用它,必須建立子類別並覆寫 paint(Graphics g) 方法。Graphics 物件封裝了所有繪圖原語(線條、矩形、文字、圖片等)。

範例:繪製 "Hello World!"

import javax.microedition.lcdui.*;

public class MyCanvas extends Canvas {
    public void paint(Graphics g) {
        // 設定紅色背景
        g.setColor(255, 0, 0);
        g.fillRect(0, 0, getWidth(), getHeight());

        // 設定白色前景並繪製文字
        g.setColor(255, 255, 255);
        g.drawString("Hello World!", 0, 0, Graphics.TOP | Graphics.LEFT);
    }
}

顯示 Canvas

因 Canvas 是 Displayable 子類,可直接用 Display.setCurrent() 顯示:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class MyMidlet extends MIDlet {
    public void startApp() {
        Canvas canvas = new MyCanvas();
        Display.getDisplay(this).setCurrent(canvas);
    }
    public void pauseApp() {}
    public void destroyApp(boolean unconditional) {}
}

Canvas 繪製 Hello World 效果圖

圖 1. 在 Canvas 上繪製 "Hello World!"

座標系統與繪圖模型

  • 原點 (0,0) 位於螢幕左上角
  • X 軸向右遞增,Y 軸向下遞增
  • 使用 getWidth()、getHeight() 取得可繪製區域尺寸
  • 採像素替換模型:以 Graphics 當前顏色直接覆蓋目標像素
  • 支援 24-bit RGB 色彩,但裝置會自動映射至可用調色盤

良好的應用應檢查裝置色彩支援:Display.isColor()、Display.numColors()。

雙緩衝:實現流暢動畫

直接在螢幕繪圖易產生閃爍。雙緩衝技術先在離屏 Image 緩衝區繪製,完成後一次性複製到螢幕:

// 建立與螢幕等大的離屏緩衝區
int w = getWidth(), h = getHeight();
Image buffer = Image.createImage(w, h);
Graphics gc = buffer.getGraphics();

// 在緩衝區繪製動畫幀
gc.drawRect(20, 20, 25, 30);

// paint() 中將緩衝區內容繪至螢幕
public void paint(Graphics g) {
    g.drawImage(buffer, 0, 0, Graphics.TOP | Graphics.LEFT);
}

可用 Canvas.isDoubleBuffered() 檢查實作是否已內建雙緩衝。

執行緒安全與重繪機制

  • MIDP GUI API 為執行緒安全,可從任何執行緒呼叫
  • 例外:Canvas.serviceRepaints() 會立即同步呼叫 paint(),若 paint() 需鎖定被 serviceRepaints() 持有的物件,會造成死結。避免在使用 serviceRepaints() 時鎖定 paint() 會用到的物件。
  • Display.callSerially(Runnable) 可在所有待處理重繪完成後,於事件執行緒執行程式碼,適合遊戲主迴圈:
class GameCanvas extends Canvas implements Runnable {
    void gameLoop() {
        // 更新遊戲狀態
        repaint();          // 排程重繪
        callSerially(this); // 重繪完成後繼續下一幀
    }
    public void run() { gameLoop(); }
}

字體系統

應用無法自行建立字體,只能透過 Font.getFont(face, style, size) 向系統請求最接近的字體。三屬性組合:

屬性可用值
FaceMONOSPACE, PROPORTIONAL, SYSTEM
SizeSMALL, MEDIUM, LARGE
StyleBOLD, ITALIC, PLAIN, UNDERLINED (可用 | 組合)

範例:Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD | Font.STYLE_UNDERLINED, Font.SIZE_MEDIUM)。系統保證永遠回傳有效的 Font 物件。

字體展示範例

public class FontCanvas extends Canvas {
    public void paint(Graphics g) {
        g.setColor(0xFFFFFF);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(0x000000);

        g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_LARGE));
        g.drawString("System Font", 0, 0, Graphics.LEFT | Graphics.TOP);

        g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM));
        g.drawString("Medium Size", 0, 15, Graphics.LEFT | Graphics.TOP);

        g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
        g.drawString("Bold Style", 0, 30, Graphics.LEFT | Graphics.TOP);

        g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_ITALIC, Font.SIZE_MEDIUM));
        g.drawString("Italic Style", 0, 45, Graphics.LEFT | Graphics.TOP);

        g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_UNDERLINED, Font.SIZE_MEDIUM));
        g.drawString("Underlined Style", 0, 60, Graphics.LEFT | Graphics.TOP);
    }
}

系統字體繪製效果圖

圖 2. 在裝置螢幕上繪製系統字體

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved