本文展示一個基於 ApplicationWindow 的完整文本瀏覽器範例,整合了選單列、工具列、狀態列、檔案開啟、非同步行數統計、圖示資源管理等 JFace 核心組件。代碼結構清晰,適合作為 RCP 風格桌面應用的起始模板。
public class FileViewer extends ApplicationWindow {
private Text text; // 核心編輯區
private String content; // 文字內容快取
private String lineDelimiter; // 換行符
// 非同步行數統計任務
private final IRunnableWithProgress runnableWithProgress = monitor -> {
System.out.println("Running from thread: " + Thread.currentThread().getName());
// UI 線程讀取文字內容
getShell().getDisplay().syncExec(() -> {
content = text.getText();
lineDelimiter = text.getLineDelimiter();
});
monitor.beginTask("Counting total number of lines", content.length());
int lines = 1;
for (int i = 0; i < content.length(); i++) {
if (monitor.isCanceled()) {
monitor.done();
System.out.println("Action cancelled");
return;
}
if (i + lineDelimiter.length() < content.length()) {
if (lineDelimiter.equals(content.substring(i, i + lineDelimiter.length()))) {
lines++;
}
}
monitor.worked(1);
try { Thread.sleep(1); } catch (InterruptedException ignored) {}
}
monitor.done();
System.out.println("Total number of lines: " + lines);
};
// Action 定義
private final Action actionCount = new Action("Count",
ImageDescriptor.createFromFile(null, "C:/icons/run.gif")) {
public void run() {
try {
run(true, true, runnableWithProgress); // fork=true, cancelable=true
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
};
private final Action actionOpenFile = new Action("Open",
ImageDescriptor.createFromFile(null, "C:/icons/open.gif")) {
public void run() {
FileDialog dialog = new FileDialog(getShell(), SWT.OPEN);
String file = dialog.open();
if (file != null) {
try {
String content = readFileAsAString(new File(file));
text.setText(content);
setStatus("File loaded successfully: " + file);
} catch (IOException e) {
e.printStackTrace();
setStatus("Failed to load file: " + file);
}
}
}
};
// 建構子
public FileViewer(Shell parentShell) {
super(parentShell);
addMenuBar();
addStatusLine();
addToolBar(SWT.FLAT);
}
// 建立內容區
@Override
protected Control createContents(Composite parent) {
getShell().setText("FileViewer v2.0");
setStatus("Ready");
text = new Text(parent, SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
text.setSize(300, 200);
return text;
}
// 選單列構建
@Override
protected MenuManager createMenuManager() {
MenuManager menuManager = new MenuManager("");
MenuManager fileMenu = new MenuManager("&File");
fileMenu.add(actionOpenFile);
menuManager.add(fileMenu);
MenuManager toolsMenu = new MenuManager("&Tools");
toolsMenu.add(actionCount);
menuManager.add(toolsMenu);
return menuManager;
}
// 工具列構建
@Override
protected ToolBarManager createToolBarManager(int style) {
ToolBarManager tbm = new ToolBarManager(style);
tbm.add(actionOpenFile);
tbm.add(actionCount);
return tbm;
}
// 檔案讀取工具方法
public static String readFileAsAString(File file) throws IOException {
return new String(getBytesFromFile(file));
}
public static byte[] getBytesFromFile(File file) throws IOException {
try (InputStream is = new FileInputStream(file)) {
long length = file.length();
if (length > Integer.MAX_VALUE)
throw new IllegalArgumentException("File too large (>2GB)");
byte[] bytes = new byte[(int) length];
int offset = 0, numRead;
while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
if (offset < bytes.length)
throw new IOException("Could not completely read file: " + file.getName());
return bytes;
}
}
// 啟動入口
public static void main(String[] args) {
ApplicationWindow viewer = new FileViewer(null);
viewer.setBlockOnOpen(true);
viewer.open();
}
}
// 1. 建構子:addMenuBar()/addToolBar()/addStatusLine()
// 2. createContents():建立中心內容區(必須覆寫)
// 3. createMenuManager()/createToolBarManager():構建選單/工具列(可選覆寫)
// 4. open():開啟視窗,進入事件循環
// 5. close():關閉視窗,釋放資源
run(true, true, IRunnableWithProgress) 自動顯示進度對話框。// IRunnableWithProgress.run(IProgressMonitor monitor)
// monitor.beginTask(taskName, totalWork)
// monitor.worked(workDone)
// monitor.isCanceled() 檢查用戶取消
// monitor.done() 結束
// 配合 Display.syncExec() 讀取 UI 組件狀態
// 延遲載入,自動處理路徑、URL、流
ImageDescriptor.createFromFile(FileViewer.class, "icons/open.gif")
ImageDescriptor.createFromURL(url)
// 實際建立 Image 時才載入,避免啟動緩慢
try-with-resources 確保流關閉。RandomAccessFile 或 MappedByteBuffer 實現虛擬滾動。Text 為 StyledText,結合 StyleRange 實現關鍵字著色。Text.findText()。PreferenceStore 持久化記錄。DropTarget 支援拖曳檔案到視窗開啟。此範例展示了 JFace ApplicationWindow 框架的標準用法:
IRunnableWithProgress + 進度監視器。ImageDescriptor 延遲載入圖示。FileDialog、訊息框等。以此為基礎,可快速構建專業級 SWT/JFace 桌面應用。