第六天課程聚焦 Applet 的「豐富客戶端」能力:跨網絡載入圖片/聲音、精細控制字體色彩、突破沙箱訪問本地/遠程資料庫。雖然 Applet 技術已退出歷史舞台,但其資源載入模型、繪圖管線、JDBC 抽象層的設計思想,仍深刻影響現代 Java 客戶端 (JavaFX/Swing) 與 Web 資源加載機制。
ImageIO 讀取)。getImage()| 類別 | 方法簽名 | 適用場景 |
|---|---|---|
java.applet.Applet | Image getImage(URL url)Image getImage(URL base, String name) | Applet 內部,相對 codeBase/documentBase |
java.awt.Toolkit | Image getImage(String filename)Image getImage(URL url) | 應用程式 (Application) 或通用工具類 |
// 本地文件 (file 協議)
URL url1 = new URL("file:/d:/image/pic1.gif");
// 遠程 HTTP 資源
URL url2 = new URL("https://abc.cde.edu.cn/applet/pic2.jpg");
// 相對於 Applet 所在頁面 (codeBase)
Image img3 = getImage(getCodeBase(), "p1.jpg");
關鍵點:getCodeBase() 返回 Applet 類文件所在目錄 URL;getDocumentBase() 返回嵌入 Applet 的 HTML 頁面 URL。網絡資源載入無需額外網絡代碼,瀏覽器自動處理連線與緩存。
// 基本繪製
g.drawImage(image1, x, y, this); // this = ImageObserver (Applet/Component)
// 指定寬高 (縮放/拉伸)
g.drawImage(image1, x, y, width, height, this);
// 指定背景色 (透明區域填充)
g.drawImage(image1, x, y, width, height, Color.blue, this);
ImageObserver 回調機制確保圖片異步載入完成後自動重繪,無需手動輪詢。
java.applet.AudioClipimport java.applet.AudioClip;
AudioClip bgSound = getAudioClip(url); // 同步載入 (輕量)
bgSound.play(); // 播放一次
bgSound.loop(); // 循環播放
bgSound.stop(); // 停止
// 一次性載入並播放 (無需保存引用)
play(getCodeBase(), "audio/welcome.au");
URL 用法與圖片完全一致。注意:Applet 沙箱限制,只能載入同源 (codeBase/documentBase) 或簽名授權的音頻資源。
Font myFont = new Font("標楷體", Font.BOLD, 14); // 名稱、風格、磅值
// 風格常量:Font.PLAIN (正常)、Font.BOLD (粗體)、Font.ITALIC (斜體)、可位或組合
Font oldFont = g.getFont(); // 保存原字體
g.setFont(myFont);
g.drawString("文字", x, y);
g.setFont(oldFont); // 恢復,良好習慣
Color myColor = new Color(0, 0, 255); // 紅、綠、藍 0-255
// 或十六進制
Color myColor = new Color(0x0000FF);
// HTML
<param name=red value=255>
<param name=green value=0>
<param name=blue value=0>
// Java
String[] para = {"red","green","blue"};
int[] rgb = new int[3];
for (int i=0; i<3; i++) rgb[i] = Integer.parseInt(getParameter(para[i]));
g.setColor(new Color(rgb[0], rgb[1], rgb[2]));
public void paint(Graphics g) {
String[] fonts = {"新細明體","標楷體","微軟正黑體"};
String[] styles = {"PLAIN","BOLD","ITALIC"};
int[] styleVals = {Font.PLAIN, Font.BOLD, Font.ITALIC};
Font old = g.getFont();
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
g.setFont(new Font(fonts[i], styleVals[j], 12));
g.drawString("請注意變化 " + fonts[i] + " " + styles[j], 20, 20*(i*3+j+1));
}
}
g.setFont(old);
// 色彩示範同上...
}
場景:Applet 讀取本機/局域網 Access (.mdb) 資料庫顯示於 TextArea。前提:已配置系統 ODBC 資料源名 (DSN)。
| 類別 | 職責 |
|---|---|
Connection | 資料庫連線物件,DriverManager.getConnection() 獲取 |
Statement | 執行靜態 SQL 語句 |
ResultSet | 查詢結果集游標 |
ResultSetMetaData | 結果集結構資訊 (列數、列名、類型) |
jdbc:odbc:<DSN名稱> // ODBC 資料源
// 範例
String dsn = "jdbc:odbc:MyAccess";
// 1. 變量宣告
TextArea dataArea = new TextArea(6, 80);
TextField statusBar = new TextField("", 80);
Connection conn;
Statement stmt;
ResultSet rs;
ResultSetMetaData meta;
public void init() {
add(dataArea); add(statusBar);
dataArea.setEditable(false); statusBar.setEditable(false);
openConnection();
execSqlCommand("SELECT * FROM MyTable");
closeConnection();
}
public void openConnection() {
String dsn = "jdbc:odbc:MyAccess";
String user = "", pwd = "";
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); // 載入驅動
conn = DriverManager.getConnection(dsn, user, pwd);
statusBar.setText("Status: OK");
} catch (Exception e) { handleException(e); }
}
public void execSqlCommand(String sql) {
try {
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
meta = rs.getMetaData();
int cols = meta.getColumnCount();
dataArea.setText("");
while (rs.next()) {
for (int i=1; i<=cols; i++) {
String val = rs.getString(i);
dataArea.append((val==null?"":val) + ";");
}
dataArea.append("\n");
}
} catch (Exception e) { handleException(e); }
}
public void closeConnection() {
try { if (conn!=null) conn.close(); }
catch (Exception e) { handleException(e); }
}
public void handleException(Exception e) {
statusBar.setText("Error: " + e.getMessage());
e.printStackTrace();
if (e instanceof SQLException) {
while ((e = ((SQLException)e).getNextException()) != null)
System.out.println(e);
}
}
MyAccess (與程式 jdbc:odbc:MyAccess 一致)。.mdb / .accdb 檔案 → 確定。MyAccess。關鍵提醒:
ClassNotFoundException 或 Data source name not found。JdbcOdbcDriver,現代專案請用 UCanAccess (純 Java) 或 Jackcess 直讀 Access,無需 ODBC。| Applet 技術 | 現代替代方案 |
|---|---|
getImage/getAudioClip | JavaFX Image/AudioClip、Swing ImageIcon/javax.sound.sampled、Web fetch()/<img>/<audio> |
Font/Color/Graphics | JavaFX Font/Paint/GraphicsContext、Swing 同包、CSS/Canvas 2D |
| JDBC-ODBC Bridge | UCanAccess (Access)、JDBC 原生驅動 (MySQL/PostgreSQL/SQL Server)、連接池 (HikariCP) |
| Applet 沙箱/簽名 | 無沙箱 (桌面應用)、Web 安全模型 (CORS/CSP/HTTPS)、簽名 JAR → 憑證信任 |