完整可執行程式碼
package swt_jface.demo;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
public class IconSelector {
private Display display = new Display();
private Shell shell = new Shell(display);
private Label labelIconFile;
private Text textIconFile;
private Button buttonIconBrowse;
private Button buttonSetIcon;
private Image shellIcon;
public IconSelector() {
initializeUI();
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
private void initializeUI() {
GridLayout layout = new GridLayout(3, false);
shell.setLayout(layout);
labelIconFile = new Label(shell, SWT.NONE);
labelIconFile.setText("選擇圖示檔案:");
textIconFile = new Text(shell, SWT.SINGLE | SWT.BORDER);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.grabExcessHorizontalSpace = true;
textIconFile.setLayoutData(gd);
buttonIconBrowse = new Button(shell, SWT.PUSH);
buttonIconBrowse.setText("瀏覽...");
buttonSetIcon = new Button(shell, SWT.PUSH);
gd = new GridData();
gd.horizontalSpan = 3;
gd.horizontalAlignment = GridData.CENTER;
buttonSetIcon.setLayoutData(gd);
buttonSetIcon.setText("設定圖示");
shell.setText("圖示選擇器");
// 瀏覽按鈕:開啟檔案選擇對話框
buttonIconBrowse.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
FileDialog dialog = new FileDialog(shell, SWT.OPEN);
dialog.setFilterNames(new String[] { "圖片檔 (*.png;*.jpg;*.ico;*.bmp)", "所有檔 (*.*)" });
dialog.setFilterExtensions(new String[] { "*.png;*.jpg;*.ico;*.bmp", "*.*" });
String file = dialog.open();
if (file != null) textIconFile.setText(file);
}
});
// 設定圖示按鈕:載入圖片並套用至 Shell
buttonSetIcon.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
String path = textIconFile.getText().trim();
if (path.isEmpty()) return;
if (shellIcon != null) shellIcon.dispose(); // 釋放舊圖示資源
try {
shellIcon = new Image(display, path);
shell.setImage(shellIcon);
} catch (Exception ex) {
ex.printStackTrace();
MessageBox mb = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
mb.setMessage("載入圖示失敗:" + ex.getMessage());
mb.open();
}
}
});
}
public static void main(String[] args) {
new IconSelector();
}
}
關鍵 API 說明
| 類別/方法 | 用途 |
Display | SWT 應用程式進入點,管理事件迴圈、資源、色彩、字體 |
Shell | 頂層視窗,setImage(Image) 設定標題列圖示 |
FileDialog | 原生檔案選擇對話框,SWT.OPEN/SWT.SAVE、過濾器、多選 |
Image(Display, String) | 從檔案路徑載入圖片(支援 PNG、JPG、BMP、ICO 等) |
Image.dispose() | 必須手動釋放 OS 圖形資源,避免洩漏 |
GridLayout/GridData | 彈性佈局管理器,支援跨欄、對齊、抓取剩餘空間 |
SelectionAdapter | 事件適配器,僅覆寫需要的方法(widgetSelected) |
資源管理最佳實踐
- Image、Font、Color、GC、Display 等 SWT 圖形資源必須手動
dispose(),不受 GC 管理。
- 建立
dispose() 習慣:try { new Image(...) } finally { if (img != null) img.dispose(); } 或使用 try-with-resources 包裝器(SWT 4.3+ 支援 AutoCloseable)。
Display 最後呼叫 dispose() 釋放所有關聯資源。
常見擴充
- 圖示預覽:在
Text 旁加 Label,setImage(new Image(display, path)) 即時顯示縮圖。
- 拖放支援:
DropTarget + Transfer 實現拖入圖片檔自動填入路徑。
- 圖示尺寸驗證:載入後檢查
image.getBounds().width/height,建議 16x16、32x32、48x48 標準尺寸。
- 跨平台 ICO 支援:Windows 原生支援 .ico;Linux/macOS 需額外解碼器或轉 PNG。