Eclipse Standard Widget Toolkit (SWT) 使用作業系統原生圖形庫,啟動快、記憶體佔用低,適合桌面應用開發。本文示範載入本地圖片、設定 Shell 大小、繪製圖片與標準事件迴路。
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.swt.win32.win32.x86_64</artifactId>
<version>3.120.0</version> <!-- 對應 Eclipse 2022-09 -->
</dependency>
其他平台請換用對應 artifactId (cocoa.macosx.x86_64, gtk.linux.x86_64 等)。
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class SwtImageDemo {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display, SWT.SHELL_TRIM | SWT.DOUBLE_BUFFERED);
shell.setText("SWT 圖片檢視器");
// 1. 載入圖片 (支援 BMP, GIF, JPEG, PNG, TIFF)
String imagePath = "C:/images/sample.jpg"; // 請替換為實際路徑
Image image;
try {
image = new Image(display, imagePath);
} catch (Exception e) {
System.err.println("圖片載入失敗: " + e.getMessage());
display.dispose();
return;
}
// 2. 依圖片尺寸調整 Shell (加上邊框補償)
Rectangle bounds = image.getBounds();
shell.setSize(bounds.width + 16, bounds.height + 39); // Windows 標題列約 39px
// 3. 設定 Shell 圖示 (可選)
shell.setImage(image);
// 4. 繪製圖片 - 必須在 PaintListener 中進行,否則視窗重繪會丟失
shell.addPaintListener(e -> {
GC gc = e.gc;
gc.drawImage(image, 0, 0); // 左上角對齊
});
shell.open();
// 5. 標準事件迴路
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
// 6. 釋放資源 (Image 必須手動 dispose)
image.dispose();
display.dispose();
}
}
| 步驟 | 說明 | 注意事項 |
|---|---|---|
| Display 建立 | SWT 應用程式進入點,管理平台資源 | 每執行緒僅能有一個 Display;主執行緒自動建立 |
| Image 建立 | 綁定特定 Display,不可跨 Display 使用 | 必須手動 dispose(),否則洩漏 GDI/記憶體 |
| PaintListener | 正確繪製時機,支援視窗最小化/遮擋後恢復 | 不要在 open() 前直接用 GC 繪製,會被擦除 |
| 事件迴路 | readAndDispatch() 處理佇列事件;sleep() 釋放 CPU | 若無 sleep() 會佔滿單核 CPU |
| 資源釋放 | Image、Display、Color、Font、GC 皆需 dispose | 建議使用 try-with-resources 或統一清理 |
shell.addPaintListener(e -> {
GC gc = e.gc;
Rectangle clientArea = shell.getClientArea();
Rectangle imgBounds = image.getBounds();
double scale = Math.min(
(double) clientArea.width / imgBounds.width,
(double) clientArea.height / imgBounds.height
);
int drawWidth = (int) (imgBounds.width * scale);
int drawHeight = (int) (imgBounds.height * scale);
int x = (clientArea.width - drawWidth) / 2;
int y = (clientArea.height - drawHeight) / 2;
gc.drawImage(image, 0, 0, imgBounds.width, imgBounds.height, x, y, drawWidth, drawHeight);
});
// 視窗大小改變時觸發重繪
shell.addListener(SWT.Resize, e -> shell.redraw());
System.setProperty("apple.laf.useScreenMenuBar", "true") 並使用 SWT.APPLICATION_MENU。