視圖是 RCP 應用主要互動介面,透視圖負責佈局視圖、編輯器、工具列。本文完整示範從 ViewPart 繼承、plugin.xml 宣告、IPerspectiveFactory 佈局,到 JFace Viewer(ListViewer/TableViewer/TreeViewer)與 ContentProvider/LabelProvider 模式的資料綁定。
// FirstView.java
public class FirstView extends ViewPart {
public static final String ID = "cn.blogjava.youxia.views.FirstView";
@Override public void createPartControl(Composite parent) {
Composite container = new Composite(parent, SWT.NONE);
// 使用 Designer 視覺化拖拉元件,或手寫 Layout
new Label(container, SWT.NONE).setText("姓名:");
Text text = new Text(container, SWT.BORDER);
// ... 更多控制項
createActions(); initializeToolBar(); initializeMenu(); // 標準三部曲
}
@Override public void setFocus() { /* 設定焦點控制項 */ }
}
<extension point="org.eclipse.ui.views">
<view class="cn.blogjava.youxia.views.FirstView"
id="cn.blogjava.youxia.views.FirstView"
name="第一個View"/>
</extension>
public class Perspective implements IPerspectiveFactory {
public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea();
// 將 FirstView 放在編輯器區域右側,寬度 20%
layout.addView(FirstView.ID, IPageLayout.RIGHT, 0.2f, editorArea);
}
}
org.eclipse.ui/SHOW_TRADITIONAL_STYLE_TABS=false // 現代風格標籤
org.eclipse.ui/DOCK_PERSPECTIVE_BAR=topRight // 透視圖切換條位置
在 plugin.xml 產品擴展點指定:
<property name="preferenceCustomization" value="plugin_customization.ini"/>
Viewer 封裝 SWT 控制項,分離資料模型與 UI:
| Viewer | 對應 SWT 控制項 | 適用場景 |
|---|---|---|
| ListViewer | List | 單欄列表 |
| TableViewer | Table | 多欄表格 |
| TreeViewer | Tree | 階層結構 |
| TextViewer | StyledText | 程式碼編輯器 |
public class Person {
private String name, sex;
// getter/setter
}
public class PersonModel {
private List<Person> list = new ArrayList<>();
public interface Listener { void add(Person p); void remove(Person p); }
private Listener listener;
public PersonModel() { /* 初始化測試資料 */ }
public void setListener(Listener l) { listener = l; }
public void add(Person p) { list.add(p); if(listener!=null) listener.add(p); }
public void remove(Person p) { list.remove(p); if(listener!=null) listener.remove(p); }
public List<Person> getElements() { return list; }
}
public class PersonContentProvider implements IStructuredContentProvider, PersonModel.Listener {
private PersonModel input;
private ListViewer viewer;
@Override public Object[] getElements(Object inputElement) {
return ((PersonModel)inputElement).getElements().toArray();
}
@Override public void inputChanged(Viewer v, Object old, Object nw) {
viewer = (ListViewer)v;
input = (PersonModel)nw;
if (input != null) input.setListener(this);
}
@Override public void dispose() { if(input!=null) input.setListener(null); }
@Override public void add(Person p) { viewer.add(p); }
@Override public void remove(Person p) { viewer.remove(p); }
}
public class PersonLabelProvider implements ILabelProvider {
@Override public String getText(Object element) {
return ((Person)element).getName(); // 顯示姓名
}
@Override public Image getImage(Object element) { return null; } // 無圖示
// 其他介面方法空實作
}
public class PatientView extends ViewPart {
private ListViewer viewer;
@Override public void createPartControl(Composite parent) {
viewer = new ListViewer(parent, SWT.BORDER);
viewer.setContentProvider(new PersonContentProvider());
viewer.setLabelProvider(new PersonLabelProvider());
viewer.setInput(new PersonModel()); // 觸發 inputChanged -> 綁定 Listener
}
}
layout.addView(viewId, position, ratio, relativeToId):position 可為 LEFT/RIGHT/TOP/BOTTOM。layout.createFolder(id, position, ratio, relativeToId):建立疊頁容器(如 Eclipse 預設的 Outline/Problems/Tasks 分頁)。layout.addActionSet(actionSetId):加入菜單/工具列 Action Set。layout.showView(viewId):預設顯示某視圖。在 ContentProvider 或 ViewPart 中為 Viewer 控制項加入 SelectionListener,取得選中物件,透過 IWorkbenchPage.showView() 或事件總線(如 EventAdmin)通知其他視圖更新詳情區。
RCP 視圖架構核心三層:ViewPart(UI 容器) + Viewer(資料綁定) + ContentProvider/LabelProvider(模型適配)。透視圖以聲明式佈局組合視圖,plugin_customization.ini 微調外觀。掌握此模式,可構建模組化、可擴展的豐富客戶端介面。