Visual Editor (VE) 是 Eclipse 基於 Java 源碼的 GUI 可視化編輯器,支援 SWT/AWT/Swing。本文以 TextItem(Label+Text 組合控件)為例,完整演示:控件實現 → BeanInfo 描述 → 屬性編輯器 → Override 機制 → Palette 擴展 → 構造參數定制 → ClassPath 容器封裝 → 運行驗證。
TextItem extends Composite,內含 Label titleLabel + Text contentText;TextItemModel (title, maxLength) 作為屬性載體;VerifyListener 限制輸入長度,beep 旗標控制超長蜂鳴;setModel() 同步模型到 UI。public class TextItemBeanInfo extends SimpleBeanInfo {
// 繼承父類屬性
public BeanInfo[] getAdditionalBeanInfo() {
try { return new BeanInfo[]{Introspector.getBeanInfo(Control.class)}; }
catch (IntrospectionException e) { return new BeanInfo[0]; }
}
// Beep 屬性:下拉枚舉
PropertyDescriptor getBeepPropertyDescriptor() {
PropertyDescriptor pd = new PropertyDescriptor("beep", TextItem.class);
pd.setDisplayName("TextItem notifier");
pd.setShortDescription("Beep when length exceed specified.");
pd.setValue("enumerationValues", new Object[]{
"No Beep", Boolean.FALSE, "pkg.TextItem.NO_BEEP",
"Beep", Boolean.TRUE, "pkg.TextItem.BEEP"
});
return pd;
}
public PropertyDescriptor[] getPropertyDescriptors() {
return new PropertyDescriptor[]{ getBeepPropertyDescriptor(), ... };
}
}
DialogCellEditor + 實現 INeedData;openDialogBox() 彈出 TitleAreaDialog,編輯 title/maxLength;<!-- plugin.xml -->
<extension point="org.eclipse.jem.beaninfo.registrations">
<registration container="pkg">
<override package="pkg" path="overrides/pkg"/>
</registration>
</extension>
<!-- overrides/pkg/TextItem.override (XMI) -->
<event:Add featureName="eStructuralFeatures">
<addedEObjects xsi:type="ecore:EReference" name="model" unsettable="true">
<eAnnotations xsi:type="ve:BasePropertyDecorator"
cellEditorClassname="pkg/pkg.TextItemModelEditor"/>
</addedEObjects>
</event:Add>
cellEditorClassname 格式:pluginId/fully.qualified.EditorClass。
<!-- palette.xmi -->
<palette:Drawer>
<entryLabel string="Custom Widgets"/>
<children xsi:type="palette:EMFCreationToolEntry"
icon16Name="platform:/plugin/pkg/icons/sample.gif"
creationClassURI="java:/pkg#TextItem">
<entryLabel string="TextItem"/>
<keyedValues key="ve.nameincomposition" value="textitem"/>
</children>
</palette:Drawer>
<extension point="org.eclipse.ve.java.core.contributors">
<palette container="pkg" categories="palette.xmi"/>
</extension>
覆蓋構造函數第二參數 SWT.NONE → SWT.BORDER:
<!-- BorderTextItem.xmi -->
<textitem:TextItem xmi:id="BorderTextItem_1">
<allocation xsi:type="jem:ParseTreeAllocation">
<expression xsi:type="jem:PTClassInstanceCreation" type="pkg.TextItem">
<arguments xsi:type="jem:PTName" name="{parentComposite}"/>
<arguments xsi:type="jem:PTFieldAccess" field="BORDER">
<receiver xsi:type="jem:PTName" name="org.eclipse.swt.SWT"/>
</arguments>
</expression>
</allocation>
</textitem:TextItem>
<cdm:AnnotationEMF annotates="BorderTextItem_1">
<keyedValues key="ve.nameincomposition" value="bordertextitem"/>
</cdm:AnnotationEMF>
在 palette.xmi 添加 EMFPrototypeToolEntry 指向此 XMI。
textitem.jar (TextItem, TextItemModel);textitembeaninfo.jar (BeanInfo, Editor);plugin.xml 註冊:<extension point="org.eclipse.jem.beaninfo.registrations">
<beaninfo path="textitembeaninfo.jar">
<searchpath package="pkg"/>
</beaninfo>
</extension>
<extension point="org.eclipse.jdt.ui.classpathContainerPage">
<classpathContainerPage name="Custom Widgets" class="ve.RegisteredClasspathContainerWizardPage" id="pkg"/>
</extension>
<extension point="org.eclipse.jdt.core.classpathContainerInitializer">
<classpathContainerInitializer class="ve.RegisteredClasspathContainerInitializer" id="pkg"/>
</extension>
<extension point="org.eclipse.ve.java.core.registrations">
<registration container="pkg" description="Custom Widgets">
<library runtime="textitem.jar"/>
</registration>
</extension>
通過 VE 擴展機制,團隊可將業務通用控件封裝為可視化組件,實現「所見即所得」的高效 UI 開發體驗。