Font 三屬性完整組合指南
Font.getFont(face, style, size) 三參數獨立正交,可自由組合:
| 屬性 | 常量 | 組合示例 |
| 面貌 | SYSTEM, MONOSPACE, PROPORTIONAL | FACE_SYSTEM |
| 風格 | PLAIN, BOLD, ITALIC, UNDERLINED | STYLE_BOLD | STYLE_ITALIC (位或運算) |
| 大小 | SMALL, MEDIUM, LARGE | SIZE_LARGE |
風格位運算詳解
// 單一風格
Font f1 = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_MEDIUM);
// 組合風格 (粗體+斜體+底線)
int style = Font.STYLE_BOLD | Font.STYLE_ITALIC | Font.STYLE_UNDERLINED;
Font f2 = Font.getFont(Font.FACE_PROPORTIONAL, style, Font.SIZE_LARGE);
// 移除風格
style = style & ~Font.STYLE_ITALIC; // 去掉斜體
完整範例:字體屬性選擇器 (ChoiceGroup 多選風格)
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class FontChooserDemo extends MIDlet implements CommandListener {
private Form form;
private ChoiceGroup faceGroup, styleGroup, sizeGroup;
private Command okCmd, exitCmd, backCmd;
private Display display;
private FontCanvas canvas;
private int face = Font.FACE_SYSTEM;
private int style = Font.STYLE_PLAIN;
private int size = Font.SIZE_MEDIUM;
public FontChooserDemo() {
form = new Form("字體屬性設定");
// 1. 面貌 (單選)
faceGroup = new ChoiceGroup("面貌", Choice.EXCLUSIVE);
faceGroup.append("SYSTEM", null);
faceGroup.append("MONOSPACE", null);
faceGroup.append("PROPORTIONAL", null);
faceGroup.setSelectedIndex(0, true);
// 2. 風格 (多選 - 關鍵:Choice.MULTIPLE)
styleGroup = new ChoiceGroup("風格", Choice.MULTIPLE);
styleGroup.append("PLAIN", null);
styleGroup.append("BOLD", null);
styleGroup.append("ITALIC", null);
styleGroup.append("UNDERLINED", null);
styleGroup.setSelectedIndex(0, true); // 預設 PLAIN
// 3. 大小 (單選)
sizeGroup = new ChoiceGroup("大小", Choice.EXCLUSIVE);
sizeGroup.append("SMALL", null);
sizeGroup.append("MEDIUM", null);
sizeGroup.append("LARGE", null);
sizeGroup.setSelectedIndex(1, true); // 預設 MEDIUM
form.append(faceGroup);
form.append(styleGroup);
form.append(sizeGroup);
okCmd = new Command("確定", Command.OK, 1);
exitCmd = new Command("離開", Command.EXIT, 1);
form.addCommand(okCmd);
form.addCommand(exitCmd);
form.setCommandListener(this);
canvas = new FontCanvas();
backCmd = new Command("返回", Command.BACK, 1);
canvas.addCommand(backCmd);
canvas.setCommandListener(this);
}
protected void startApp() {
display = Display.getDisplay(this);
display.setCurrent(form);
}
protected void pauseApp() {}
protected void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable d) {
if (d == form) {
if (c == exitCmd) { destroyApp(false); notifyDestroyed(); }
else if (c == okCmd) {
// 讀取面貌
face = new int[]{Font.FACE_PROPORTIONAL, Font.FACE_MONOSPACE, Font.FACE_SYSTEM}
[faceGroup.getSelectedIndex()];
// 讀取大小
size = new int[]{Font.SIZE_SMALL, Font.SIZE_MEDIUM, Font.SIZE_LARGE}
[sizeGroup.getSelectedIndex()];
// 讀取風格 (多選位運算)
style = 0;
boolean[] selected = new boolean[4];
styleGroup.getSelectedFlags(selected);
if (selected[0]) style |= Font.STYLE_PLAIN;
if (selected[1]) style |= Font.STYLE_BOLD;
if (selected[2]) style |= Font.STYLE_ITALIC;
if (selected[3]) style |= Font.STYLE_UNDERLINED;
display.setCurrent(canvas);
}
} else if (d == canvas) {
if (c == backCmd) display.setCurrent(form);
}
}
class FontCanvas extends Canvas {
public FontCanvas() {
addCommand(backCmd);
setCommandListener(this);
}
protected void paint(Graphics g) {
// 關鍵:每幀必清除畫面
g.setColor(0xFFFFFF); // 白底
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(0x000000); // 黑字
Font f = Font.getFont(face, style, size);
g.setFont(f);
String txt = "Hello J2ME Font";
g.drawString(txt, getWidth()/2, getHeight()/2,
Graphics.HCENTER | Graphics.VCENTER);
}
}
}
ChoiceGroup 多選模式 (MULTIPLE) 核心 API
| 方法 | 說明 |
getSelectedFlags(boolean[]) | 批次讀取所有項目選中狀態,陣列長度需 >= size() |
setSelectedFlags(boolean[]) | 批次設定選中狀態 |
isSelected(int index) | 檢查單項是否選中 |
getSelectedIndex() | 僅返回第一個選中項索引 (不適合多選) |
畫面清除機制:低層 UI 鐵律
Canvas 無自動清除,每幀 paint() 必須以 fillRect 或 drawImage(背景) 覆蓋全螢幕,否則上一幀殘影疊加。
// 標準清除模式
protected void paint(Graphics g) {
// 1. 純色清除
g.setColor(0xFFFFFF); // 背景色
g.fillRect(0, 0, getWidth(), getHeight());
// 或 2. 背景圖清除 (若有背景圖)
// g.drawImage(bgImage, 0, 0, Graphics.TOP | Graphics.LEFT);
// 3. 繪製前景內容...
g.setColor(0x000000); // 前景色
// ...
}
常見錯誤與修正
| 錯誤代碼 | 現象 | 修正 |
public void MyCanvas() | 建構子加 void 變成方法,物件不建立 | public MyCanvas() (無返回類型) |
忘記 fillRect | 文字/圖形疊加、殘影 | 每幀首行 g.fillRect(0,0,w,h) |
用 getSelectedIndex() 讀多選 | 只得第一個選中項 | 用 getSelectedFlags(boolean[]) |
風格直接相加 STYLE_BOLD + STYLE_ITALIC | 數值錯誤 (非位運算) | STYLE_BOLD | STYLE_ITALIC |
效能優化建議
- Font 物件緩存復用:
setFontSize() 時建立新 Font,paint() 直接用緩存,避免每幀 getFont()。
- 背景圖若不變,
drawImage 比 fillRect 更有質感且同等快。
- 大量文字繪製時,預先計算
stringWidth() 佈局座標,避免 paint 內重複計算。