Eclipse 平台基於 SWT(Standard Widget Toolkit)構建,而大量成熟的開發工具使用 Swing 構建 UI。完全重寫 Swing 應用為 SWT 成本極高。本文介紹一種不依賴內部 API、遵循插件規範的集成方案,實現 Swing 編輯器與 Eclipse Workbench 的雙向協作。

關鍵設計決策:避免 Swing 與 SWT 組件直接嵌入,而是讓它們擁有獨立的視窗框架,由插件單例類協調數據交換與事件傳遞。
org.eclipse.jumpstart.editorintegrationEditorintegrationPlugin 類(繼承 AbstractUIPlugin)在 Java Build Path 添加:
org.eclipse.core.resources/resources.jarorg.eclipse.jdt.core/jdtcore.jarorg.eclipse.jdt.ui/jdt.jarorg.eclipse.swt/swt.jarorg.eclipse.ui/workbench.jar<extension point="org.eclipse.ui.editors">
<editor
name="Ed - Swing Editor"
default="true"
icon="icons/thirdparty.gif"
filenames="ThirdParty.java"
launcher="org.eclipse.jumpstart.editorintegration.EdLauncher"
id="org.eclipse.jumpstart.editorintegration.ed">
</editor>
</extension>
注意:必須包含 icons/thirdparty.gif,否則 "Open With" 選單顯示異常。
package org.eclipse.jumpstart.editorintegration;
import org.eclipse.core.resources.IFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.ui.IEditorLauncher;
public class EdLauncher implements IEditorLauncher {
@Override
public void open(IFile file) throws Exception {
ICompilationUnit cu = (ICompilationUnit) JavaCore.create(file);
if (cu != null) {
// 將源碼加載到 Swing 編輯器
EditorintegrationPlugin.getDefault().getEd().getEditorPane().setText(cu.getSource());
EditorintegrationPlugin.getDefault().getEd().show();
// 記錄項目與包信息,供保存時使用
EditorintegrationPlugin.getDefault().getEd().setProjectName(file.getProject().getName());
EditorintegrationPlugin.getDefault().getEd().setPackageName(getPackagePath(file));
}
}
private String getPackagePath(IFile file) {
// 實現邏輯:從 IFile 解析包路徑
return "";
}
}
在 Swing 編輯器的 "Save" 按鈕添加事件監聽器,調用工具類方法:
public void saveButtonPressed() {
try {
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IProject project = root.getProject(ed.getProjectName());
IFolder folder = project.getFolder(ed.getPackageName());
IPackageFragment pkg = (IPackageFragment) JavaCore.create(folder);
if (pkg != null) {
ICompilationUnit cu = pkg.getCompilationUnit("ThirdParty.java");
String source = ed.getEditorPane().getText();
cu.getBuffer().setContents(source);
cu.save(null, true); // 交由平台持久化
}
} catch (Exception e) {
e.printStackTrace();
}
}
實現 IElementChangedListener 監聽 JDT 元素變更:
public void elementChanged(ElementChangedEvent event) {
IJavaElementDelta delta = event.getDelta();
if (delta != null && delta.getElement().getElementName().equalsIgnoreCase("ThirdParty.java")) {
// 更新 Swing 編輯器面板
String newSource = ((ICompilationUnit) delta.getElement()).getSource();
ed.getEditorPane().setText(newSource);
}
}
非 Java 資源變更可用 IResourceChangeListener。
在 plugin.xml 添加擴展點:
<extension point="org.eclipse.ui.preferencePages">
<page
name="Swing Editor Preference Page"
class="org.eclipse.jumpstart.editorintegration.EdPreferencePage1"
id="SwingEditorPreferencePage">
</page>
</extension>
偏好頁面類繼承 PreferencePage 並實現 IWorkbenchPreferencePage:
protected void performApply() {
Color newColor = new Color(redSlider.getSelection(), greenSlider.getSelection(), blueSlider.getSelection());
EditorintegrationPlugin.getDefault().getEd().getContentPane().setBackground(newColor);
}
public boolean performOk() {
getPreferenceStore().setValue("redValue", redSlider.getSelection());
getPreferenceStore().setValue("greenValue", greenSlider.getSelection());
getPreferenceStore().setValue("blueValue", blueSlider.getSelection());
return true;
}

為 Swing 編輯器添加 "Referenced Projects" 按鈕,點擊彈出 SWT 對話框顯示項目引用:
private String[] getReferencedProjects(String projectName) {
try {
IProject[] refs = ResourcesPlugin.getWorkspace().getRoot()
.getProject(projectName).getReferencedProjects();
if (refs.length == 0) return new String[]{"none"};
String[] names = new String[refs.length];
for (int i = 0; i < refs.length; i++) names[i] = refs[i].getName();
return names;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public class SWTProjectReferenceFrame implements Runnable {
private Shell shell;
private Display display;
private String[] projectNames;
public SWTProjectReferenceFrame(String[] projects) {
this.projectNames = projects;
}
@Override
public void run() { open(); }
public void open() {
display = new Display();
shell = new Shell(display);
shell.setLayout(new GridLayout());
shell.setText("Projects Referenced - SWT Frame");
shell.setSize(400, 400);
createListGroup();
shell.open();
// 獨立線程運行事件循環,避免阻塞 Swing 重繪
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
EditorintegrationPlugin.getDefault().getEd().repaint();
display.sleep();
}
}
}
private void createListGroup() {
Group group = new Group(shell, SWT.NONE);
group.setLayout(new GridLayout());
group.setLayoutData(new GridData(GridData.FILL_BOTH));
List list = new List(group, SWT.V_SCROLL | SWT.BORDER);
list.setItems(projectNames);
list.setLayoutData(new GridData(GridData.FILL_BOTH));
}
}

通過單例工具類解耦 Swing 與 SWT,利用 Eclipse 標準擴展點實現編輯器註冊、雙向同步、偏好配置與 Workbench 感知功能,可在不重寫現有代碼的前提下快速集成 Swing 工具。這為遺留系統現代化提供了務實路徑。