程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 擴展Visual Editor的控件和屬性

擴展Visual Editor的控件和屬性

編輯:關於JAVA

擴展 Visual Editor 的控件和屬性

Visual Editor for Java 是基於 eclipse 的 GUI 可視化編輯插件,該插件以 Java 代碼為中心,實現了所見即所得的用戶界面編輯方式,廣泛支持目前的 SWT、AWT、Swing 等控件包。本文通過一個完整的對 Visual Editor 的擴展示例,向讀者展示擴展 Visual Editor 的控件和屬性的方法。

背景

Visual Editor for Java 實現了基於 Java 源代碼的所見即所得的用戶界面開發模式。當 Java 源代碼打開後,Visual Editor 將對其進行解析,尋找可以識別的控件,並將其展現至圖形化的編輯器中,其外觀和運行時完全一致。支持用戶由 Palette 引發的控件拖拽的操作,支持對控件屬性的編輯,同時實時的生成相應的代碼。

圖 1:Visual Editor 工作區概覽

如上圖截圖所示,Visual Editor 的編輯區主要由五部分構成:

圖形編輯區,所見即所得的反映用戶界面的情況。

Java代碼區,為圖形區用戶界面對應的 Java 源碼,與圖形區同步。

Palette 區,提供了所有已擴展的,供用戶選用的 Visual Beans,用戶可以拖拽控件至圖形區定制界面。若 Palette 裡沒有列出的控件同時該控件也在 Class Path 中的情況,可以選用按鈕進行對控件的手動選擇。

屬性視圖,顯示當前選中的控件可編輯的所有信息。該視圖中的屬性更改,直接同步於 Java 代碼區的代碼,同時,UI相關的更改也會反映至圖形編輯區。對於比較簡單的類型的屬性,比如字符串類型或布爾類型,可以直接在視圖中更改,對於復雜的類型,比如字體或顏色等,則可以擴展 Property Editor 對其進行編輯。

Java Beans視圖,展示目前定制了的所有控件的層次關系。在該視圖進行的選擇或右鍵點擊等操作,實現的效果與圖形編輯區相同,選擇操作與另外的幾個區同步。

Visual Editor 各部分的交互情況,可以由下圖表示,該圖中初始化動作,就是通過對 Java 代碼的解析,將其內容反應至屬性視圖或者屬性編輯器中,這是代碼生成的逆過程。

圖 2:Visual Editor 各模塊交互圖

Palette 中提供了常用的 UI 控件的實現,包括 Swing、AWT、SWT 等的支持。如果用戶希望根據自身需求,定制所需的控件,又希望能夠通過 Visual Editor 進行識別和編輯,則需要對 Visual Editor 進行相應的擴展。這就是本文講述的內容。

引言

本文希望對 Visual Editor 進行擴展,加入符合特定業務邏輯的控件,該控件的需求如下:

為 SWT 控件,是 Label 和 Text 兩個控件的組合,其中 Label 要顯示 Text 控件的提示信息,而用戶可以在 Text 中輸入相應內容。下圖是用戶名的例子:

用戶名

可以對 Text 控件的輸入長度進行控制,比如最大輸入 8 個字符,則輸入 8 個字符後將無法繼續輸入。

可以選擇當輸入超出設定時,是否發出 Beep 聲音提醒。

在該實例過程中,本文將說明如何:

擴展一個 Java Build Path 的 Library。

擴展 Palette 中的控件。

擴展屬性視圖顯示定制控件信息。

觸發屬性編輯器來編輯控件屬性。

將代碼與屬性編輯器相互同步。

控件實現

TextItem 是該控件的具體實現,讀者可以參閱本文附件的源碼,需要提及的是:

TextItem 繼承於 SWT 的 Composite 控件,在 Composite 中包括 Label 和 Text 兩個 SWT 控件,Label 用以顯示 Title,Text 用以用戶輸入。

采用 TextItemModel 定義該控件的屬性,該 Model 是一個 Java Bean,由 Title 和 Max Length 兩個屬性構成。抽象出一個模型類主要為了增加該控件的復雜度,並展示如何通過 Property Editor 編輯該模型類。設定 TextItemModel 的代碼段:

清單1:設置 TextItemModel

public void setModel(TextItemModel model){
     this.model = model;
     titleLabel.setText(model.getTitle());
     this.pack();
   }

通過名為 beep 的布爾變量定義是否需要 beep 提醒。

添加 Verify Listener 檢測用戶輸入是否超出最大輸入字符的限制,該部分代碼如下:

清單 2: 判斷字符長度越界

contentText.addVerifyListener(new VerifyListener(){
     public void verifyText(VerifyEvent e) {
       String startStr = ((Text) e.widget).getText().substring(0, e.start);
       String endStr = ((Text) e.widget).getText().substring(e.end);
       String str = startStr + e.text + endStr;
       if ((model != null) && (str.length() > model.getMaxLength())) {
         e.doit = false;
         if (beep)
           Display.getCurrent().beep();
       }
     }
   });

BeanInfo 實現

BeanInfo 類實現了 java.beans.BeanInfo 接口,它被 Visual Editor 用來描述控件在屬性視圖中的行為。因為 BeanInfo 類僅在設計用戶界面時被用到,因此運行時是不需要該類的。Visual Editor 定義了一些規則,用以將 BeanInfo 類與其描述的控件相聯系起來,正如下文所述。

控件可以繼承其父類或其他控件的屬性行為,由 java.beans.Introspector 來獲取相應控件的 BeanInfo 描述,並作為 getAdditionalBeanInfo() 方法的返回值,就可以將其他控件的屬性行為繼承至本控件,如下面代碼所示:

清單 3:繼承控件的屬性行為

public BeanInfo[] getAdditionalBeanInfo() {
     try{
       return new BeanInfo[]{Introspector.getBeanInfo(Control.class)};
     } catch (IntrospectionException e){
       return new BeanInfo[0];
     }
   }

java.beans.PropertyDescriptor 用以描述控件的屬性,該屬性應該在控件中存在一對公開的(public 的) Get 方法和 Set 方法進行訪問。例如,setName(String name) 和 getName() 方法,對應的 property 的名字就是“name”,注意第一個字母是小寫。對 PropertyDescriptor 還有很多可選的設定,比如設定該 property 是否顯示,在屬性視圖中顯示的名稱以及該屬性的描述等。

以本控件的 Beep 屬性為例,該屬性是一個布爾型屬性,對應文本框是否有超出輸入長度的聲音提示。描述該屬性的 PropertyDescriptor 如下:

清單4:描述 Beep 屬性的 PropertyDescriptor

public PropertyDescriptor getBeepPropertyDescriptor(){
     PropertyDescriptor pd;
     try {
       pd = new PropertyDescriptor("beep", TextItem.class);
       pd.setDisplayName("TextItem notifier");
       pd.setShortDescription("Beep when the length exceed specified.");
       pd.setValue("enumerationValues", new Object[] {
       "No Beep", Boolean.FALSE, "developerworks.ve.example.textitem.TextItem.NO_BEEP",
       "Beep", Boolean.TRUE, "developerworks.ve.example.textitem.TextItem.BEEP"});
     } catch (IntrospectionException e) {
       pd = null;
     }
     return pd;
   }

PropertyDescriptor 的構造函數傳入的參數分別為屬性名稱和控件類,通過這兩個信息就可以反射獲取到控件類中某一屬性特定的內容。該屬性顯示在屬性視圖中的效果如下圖所示:

圖 3:屬性視圖結構

對應代碼來看:

setDisplayName() 用以定義該屬性在屬性視圖中顯示的名稱,如上圖中所示“TextItem notifier”;

setShortDescription() 用以設置對該屬性的文字描述,該描述會在選中該屬性時顯示在狀態欄的左方,如上圖所示“Beep when the length exceed specified.”;

setValue() 設置該屬性對應的值。因為本屬性是布爾型,所以希望做出下拉列表框的樣式,所以 setValue() 方法的 key 設置為了枚舉類型“enumerationValues”,後續的六個參數每三個為一組,表達下拉列表框中的一個選項。它們的意思分別是顯示的字符串、實際對應的值以及與生成代碼對應的初始化字符串。以前三個參數而言,“No Beep”是顯示的字符串,其對應的值是 false,即調用該控件的 setBeep(false),而在代碼編輯區生成的代碼行如下:

textitem.setBeep(developerworks.ve.example.textitem.TextItem.NO_BEEP);

在 BeanInfo 類中,體現對屬性描述的方法是 getPropertyDescriptors(),它返回上文所述的 PropertyDescriptor 的一個數組,每個 PropertyDescriptor 都包含了對該控件的某個屬性的具體描述。

屬性編輯器的實現

對 TextItem 的 TextItemModel 屬性來說,它是一個定制的屬性類,而不是簡單的數據類型或者字符串類型,對於它,用戶可能希望擁有獨立的編輯器對其進行編輯,實現的效果大概像下面的樣子:

圖 4:屬性編輯器預覽

該屬性編輯對話框是 TitleAreaDialog 的一個實現,實現過程略去不談,如何在屬性視圖中激活該對話框?

屬性視圖中每個屬性都是 key 和 value 的集合,對於 Value 的設置,可以是簡單的文本框,比如字符串型,整數型等,也可以是下拉列表框,如布爾型等。與此同時,也可以實現為彈出對話框的編輯框。該種類的編輯框可以是 JFace 的 DialogCellEditor 的實現子類,並繼承 Visual Editor 的 INeedData 接口。DialogCellEditor 是抽象類,它的唯一的抽象方法就是 openDialogBox(),用以打開上圖所示的對話框。

定制化的編輯框,如何建立與控件相應屬性的連接?這需要借助 Visual Editor 的 override 機制。BeanInfo 提供了 override 的技術,用以擴展屬性的編輯行為。Visual Editor 通過 override 文件來擴展出豐富的可定制化的編輯器。

向 Visual Editor 擴展 override 文件,需要對“org.eclipse.jem.beaninfo.registrations”擴展點進行擴展,使其能夠識別擴展的 Override 文件的位置。本例中的擴展如下:

清單 5:org.eclipse.jem.beaninfo.registrations 擴展點

<extension
     point="org.eclipse.jem.beaninfo.registrations">
    <registration
       container="developerworks.ve.example.textitem">
     <override
        package="developerworks.ve.example.textitem"
        path="overrides/developerworks/ve/example/textitem">
     </override>
    </registration>
   </extension>

其中,path 指向保存 override 文件的路徑。對應於 TextItem 而言,其 override 文件為 TextItem.override,該文件的目的就是由定制話的編輯行為覆蓋掉原有屬性的編輯行為。本例中的 TextItem.override 如下:

清單 6:Override 文件清單

<?xml version="1.0" encoding="UTF-8"?>
<xmi:XMI xmi:version="2.0"
   xmlns:xmi="http://www.omg.org/XMI"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:org.eclipse.ve.internal.cde.decorators=
            "http:///org/eclipse/ve/internal/cde/decorators.ecore"
   xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
   xmlns:event="event.xmi">
   <event:Add featureName="eStructuralFeatures">
     <addedEObjects xsi:type="ecore:EReference" name="model" unsettable="true">
     <eAnnotations xsi:type="org.eclipse.ve.internal.cde.decorators:BasePropertyDecorator"
       cellEditorClassname=
         "developerworks.ve.example.textitem/ \
            developerworks.ve.example.textitem.TextItemModelEditor" />
     </addedEObjects>
   </event:Add>
</xmi:XMI>

該文件中值得注意的幾個地方地方:

name=“model”,建立了與名為 model 的屬性的連接,即可以通過 setModel() 與 getModel() 訪問該屬性,這與前面編寫的控件行為一致。

cellEditorClassname 一項,指向了定制化後的編輯器類,該屬性的值,分割線“/”前為該編輯器所在插件的 id,分割線後為該編輯器的類路徑。

通過上述幾步操作,即可以用定制化的編輯器行為覆蓋掉 BeanInfo 中缺省的編輯器行為,實現了對屬性編輯的自由擴展。

屬性編輯器與 Java 代碼的同步

屬性編輯器與 Java 代碼有同步的需求,即可以將已經生成的 Java 代碼進行解析,將解析的結果賦給打開後的屬性編輯器顯示,同時又需要對用戶在屬性編輯器中輸入的信息進行解析,並生成 Java 代碼。這兩個是互逆的過程。

Visual Editor 的核心部分,是描述被編輯控件的EMF模型,該模型描述了控件實例,控件之間的各種關系,以及可對控件進行編輯操作的各種屬性等內容。該模型的實例實現了 org.eclipse.jem.internal.instantiation.base.IJavaInstance 接口。也就是所,上述的解析 Java 代碼的過程,可以轉化為解析 IJavaInstance 對象的過程;而生成 Java 代碼的過程,也就是生成 IJavaInstance 對象的過程。

如何解析 IJavaInstance 對象?對於本例來講,下面是解析的一個片段,可以看到,對 IJavaObjectInstance 對象的解析,就是對其主體構造函數的解析,因為 set 和 get 方法對該屬性操作,會創建一個該屬性對象對應的實例,該創建就是通過構造函數。解析出該構造函數,就可以還原該對象的內容。getArguments() 方法,就是獲取該構造函數傳入的參數,由這些參數,最終還原出該對象。

清單 7:解析 IJavaObjectInstance 對象

JavaAllocation allocation = ((IJavaObjectInstance) getValue()).getAllocation();
   PTExpression exp = ((ParseTreeAllocation) allocation).getExpression();
   PTClassInstanceCreation instance = ((PTClassInstanceCreation) exp);
   PTStringLiteral stringLiteral = (PTStringLiteral) instance.getArguments().get(0);
   String title = stringLiteral.getLiteralValue();
   PTNumberLiteral numberLiteral = (PTNumberLiteral) instance.getArguments().get(1);
   int max = Integer.parseInt(numberLiteral.getToken());
   model = new TextItemModel(title, max);

如何生成 Java 代碼?即如何生成 IJavaObjectInstance 的實例?還是要回到構造函數上來,通過初始化字符串,傳入正確類型的參數,生成相應的構造函數語句,就能夠創建出 Visual Editor 可識別的 IJavaObjectInstance 實例,從而轉化為代碼編輯區中的 Java 代碼。本例中解析的代碼如下:

清單8:創建 IJavaObjectInstance 實例

private static final String TEXTITEMMODELCLASSPATH =
             "developerworks.ve.example.textitem.TextItemModel";
   private IJavaInstance createJavaObject(TextItemModel model) {
     return BeanUtilities.createJavaObject(TEXTITEMMODELCLASSPATH,
                JavaEditDomainHelper.getResourceSet(editDomain),
         getJavaAllocation(model));
   }
   private JavaAllocation getJavaAllocation(TextItemModel model) {
     String initString = "new " + TEXTITEMMODELCLASSPATH +
       "(" + "\"" + model.getTitle() + "\", " + model.getMaxLength() + ")";
     return BeanPropertyDescriptorAdapter.createAllocation(initString, editDomain);
   }

擴展控件至 Palette

到目前為止,圍繞該控件的編碼工作已經完成:擁有了定制化的控件,描述該控件的 BeanInfo,以及對該控件進行編輯的編輯器。下一步要做的就是將該控件集成到 Visual Editor 的編輯器中,供用戶使用了。

如何擴展該控件至 Palette?Visual Editor 的 Palette 由 EMF 的模型來描述,EMF 可以序列化為 XMI,而插件可以定制它們自己的XMI文件,描述控件的種類,歸屬於哪些控件組,以及圖標和實現類等信息。對於本例中的 TextItem 來講,編寫了 palette.xmi 文件來描述該控件,使其被 Palette 所識別,對應於 TextItem,是<children></children>中的內容,分別描述了該控件由哪種圖標表示,實現類是哪個,在 Palette 中顯示的名稱,以及創建後的實例,默認采用的名稱。

清單 9:Palette.xmi 文件

<?xml version="1.0" encoding="UTF-8"?>
<org.eclipse.ve.internal.cde.palette:Drawer xmi:version="2.0"
xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
xmlns:org.eclipse.ve.internal.cde.palette=
     "http:///org/eclipse/ve/internal/cde/palette.ecore"
xmlns:org.eclipse.ve.internal.cde.utility=
      "http:///org/eclipse/ve/internal/cde/utility.ecore">
  <entryLabel xsi:type="org.eclipse.ve.internal.cde.utility:ConstantString"
       string="Custom Widgets"/>
  <children xsi:type="org.eclipse.ve.internal.cde.palette:EMFCreationToolEntry"
   icon16Name="platform:/plugin/developerworks.ve.example.textitem/icons/sample.gif"
   creationClassURI="java:/developerworks.ve.example.textitem#TextItem">
   <entryLabel xsi:type="org.eclipse.ve.internal.cde.utility:ConstantString"
       string="TextItem"/>
   <keyedValues xsi:type="ecore:EStringToStringMapEntry"
    key="org.eclipse.ve.internal.cde.core.nameincomposition" value="textitem"/>
  </children>
</org.eclipse.ve.internal.cde.palette:Drawer>

該 palette.xmi 文件,需要 Visual Editor 知道其路徑,因此需要在對“org.eclipse.ve.java.core.contributors”擴展點做如下擴展,使其能夠讀取到擴展的定義文件。

清單10:“org.eclipse.ve.java.core.contributors”擴展點

<extension
     point="org.eclipse.ve.java.core.contributors">
    <palette
       container="developerworks.ve.example.textitem"
       categories="palette.xmi"/>
  </extension>

更改控件的創建參數

經過上述定制,控件已經顯示於 Palette 中,拖拽控件至圖形編輯區已經可以預覽該控件和生成相應的代碼,生成控件的 Java 代碼為 new TextItem(parent, SWT.NONE)。也就是說,控件生成傳入構造函數的參數,第二項 style 默認為 SWT.NONE。如果希望該控件構造函數傳入的參數 style 為 SWT.BORDER 或其他樣式,如何定制呢?

Visual Editor 提供了這種定制的支持,同樣依賴於 XMI 文件,實現對構造函數默認參數的覆蓋。本例中,BorderTextItem 是 TextItem 的另一種使用,不同點僅在於生成代碼中,構造函數傳入參數不同。BorderTextItem 傳入的 style 參數為 SWT.BORDER,並將該樣式賦給了該控件的文本框。覆蓋該構造函數參數的 XMI 文件如下:

清單 11:BorderTextItem.xmi

<?xml version="1.0" encoding="UTF-8"?>
<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
  xmlns:cdm="http:///org/eclipse/ve/internal/cdm.ecore"
  xmlns:utility="http:///org/eclipse/ve/internal/cde/utility.ecore"
  xmlns:org.eclipse.jem.internal.instantiation=
           b"http:///org/eclipse/jem/internal/instantiation.ecore"
  xmlns:java="java.xmi"
  xmlns:textitem="java:/developerworks.ve.example.textitem">
  <textitem:TextItem xmi:id="BorderTextItem_1">
    <allocation xsi:type="org.eclipse.jem.internal.instantiation:ParseTreeAllocation">
    <expression xsi:type="org.eclipse.jem.internal.instantiation:PTClassInstanceCreation"
    type="developerworks.ve.example.textitem.TextItem">
     <arguments xsi:type="org.eclipse.jem.internal.instantiation:PTName"
        name="{parentComposite}"/>
     <arguments xsi:type="org.eclipse.jem.internal.instantiation:PTFieldAccess"
        field="BORDER">
      <receiver xsi:type="org.eclipse.jem.internal.instantiation:PTName"
       name="org.eclipse.swt.SWT"/>
     </arguments>
    </expression>
   </allocation>
  </textitem:TextItem>
  <cdm:AnnotationEMF annotates="BorderTextItem_1">
   <keyedValues xmi:type="ecore:EStringToStringMapEntry"
   key="org.eclipse.ve.internal.cde.core.nameincomposition" value="bordertextitem"/>
  </cdm:AnnotationEMF>
</xmi:XMI>

本文件中,<textitem:TextItem> </textitem:TextItem>標記符內的內容就是該控件的定義。

這裡的TextItem規范了該控件的返回類型,即創建該控件後賦予的引用的類型。其地位如同“TextItem item = new TextItem(parent, SWT.BORDER)”語句中的左端的返回類型 TextItem。PTClassInstanceCreation 就是創建該控件的語句,裡面傳入的 arguments 就是構造函數的傳入參數 parent 和 SWT.BORDER。對於第二項參數,替換了原有的創建行為 SWT.NONE,receiver 的名稱為 org.eclipse.swt.SWT,field 就是 BORDER,這就意味著構造函數傳入的第二個參數為 SWT.BORDER 了。之後要做的就是在表示 Palette 的 palette.xmi 中增加一個控件項,將該控件項與此 XMI 文件做連接,就完成了構造函數參數的覆蓋。加入的控件項如下:

清單 12:palette.xmi 文件中 BorderTextItem 定義

<children xsi:type="org.eclipse.ve.internal.cde.palette:EMFPrototypeToolEntry"
   icon16Name="platform:/plugin/developerworks.ve.example.textitem/icons/sample.gif"
   icon32Name="" id=""
   prototypeURI="platform:/plugin/developerworks.ve.example.textitem/ \
            palette/BorderTextItem.xmi#BorderTextItem_1">
   <entryLabel xsi:type="org.eclipse.ve.internal.cde.utility:ConstantString"
   string="BorderTextItem"/>
  </children>

prototyleURI 指向了定義該控件的位置,即 developerworks.ve.example.textitem 插件下的 palette 文件夾內的 BorderTextItem.xmi 文件,對應該文件中的 BorderTextItem_1 創建項。由此建立了 Palette 與構造函數的 XMI 文件的聯系。

定義 ClassPath 容器

用戶如何將定制化的控件加到他們的構建路徑裡?和 JRE System Library 一樣,如果我們的控件打包為 textitem.jar,他們可能希望有下圖演示的方便的構建方式:

圖 5:添加 Class Library 預覽

如何定制 ClassPath 容器?

首先區分一下,本文前述的 Java 類,哪些需要在 runtime 時使用,哪些僅僅是 Visual Editor 使用:

TextItem 控件類,是控件的具體實現,TextItemModel 類,是該控件類的模型類,這兩個類是 runtime 類,在用戶的應用程序中會采用。

TextItemBeanInfo 類,是描述 TextItem 屬性編輯行為的類,而 TextItemModelEditor 類,是對應於 TextItemModel 的屬性編輯器,這兩個類屬於在 Visual Editor 下使用的類,用戶並不關心他們內部的實現。

所以,打包 runtime 用的 jar 包,僅需將 TextItem 類和 TextItemModel 類打包為 textitem.jar,這是創建 ClassPath 容器的第一步。而 TextItemBeanInfo 和 TextItemModelEditor 為插件擴展才會用到的類,則可以另外打包為 textitembeaninfo.jar,放入導出的插件中,並對擴展點“org.eclipse.jem.beaninfo.registrations”進行擴展,令 Visual Editor 能夠找到擴展的 BeanInfo 類和屬性編輯器類:

清單 13:擴展 BeanInfo 項

<beaninfo path="textitembeaninfo.jar">
  <searchpath package="developerworks.ve.example.textitem"/>
</beaninfo>

之後就是將 textitem.jar 做成 Class Library 並加入到 Class Path 容器中了。該步需要對 eclipse 的 jdt 的一些擴展點做擴展,擴展如下,可以參閱 eclipse 的幫助文件中擴展點的說明了解各擴展點的含義,此處不再詳述:

清單 14:擴展 Classpath Container Page 擴展點

<extension point="org.eclipse.jdt.ui.classpathContainerPage">
    <classpathContainerPage name="Custom Widgets"
    class="org.eclipse.ve.internal.java.wizard.RegisteredClasspathContainerWizardPage"
       id="developerworks.ve.example.textitem">
    </classpathContainerPage>
  </extension>
  <extension point="org.eclipse.jdt.core.classpathContainerInitializer">
    <classpathContainerInitializer
    class="org.eclipse.ve.internal.java.core.RegisteredClasspathContainerInitializer"
       id="developerworks.ve.example.textitem">
    </classpathContainerInitializer>
  </extension>
  <extension point="org.eclipse.ve.java.core.registrations">
    <registration
       container="developerworks.ve.example.textitem"
       description="Custom Widgets">
     <library runtime="textitem.jar"/>
    </registration>
</extension>

使用定制後的控件

至此,定制控件的插件已經完成。將該插件打包放入 eclipse 的 plugin 文件夾下,重啟 eclipse,就可以激活該插件,在 Visual Editor 中使用定制後的控件了。下面從使用者的角度貫穿一下如何使用該定制控件,讀者可以根據每個步驟,思考在本文中是如何實現該步驟的功能的:

Step1:創建 Java 的 Project,將名為 Custom Widgets 的 ClassPath 容器以及 SWT 的類容器加入項目的構建路徑:

圖 6:添加構建路徑

Step2: 創建 Visual Class,可以在 Style 中選中 SWT 的 Composite 或 Shell 作為該 Visual Class 的基類面板,這裡選擇為 Composite:

圖 7:新建 Visual Class

Step3:由 Palette 中拖拽 TextItem 或 BorderTextItem 至圖形編輯區的 Composite 上,代碼編輯區可以相應生成代碼。

圖 8:拖拽控件

Step4:在屬性視圖中編輯該控件的屬性“TextItem notifier”設置為 BEEP,由 TextItem model 的編輯器打開編輯對話框,輸入 Title為“User Name: ”,最大長度為 8。

圖 9:編輯屬性

Step5:運行該 Java 文件,預覽一下成果,運行效果應該如下圖所示,當在文本框中輸入的用戶名字符數超過 8 個,則會有 Beep 的聲音提示:

圖 10:運行截圖

結束語

本文向您闡述了如何擴展 Visual Editor,加入定制化的控件供用戶使用,以及相關的很多問題和解決方案,供您參考。通過這種定制,用戶可以很容易的所見即所得的將定制後的控件放到他們希望的地方,並能夠圖形化的編輯該控件的各種屬性,使得開發 Java 用戶界面的工作變得簡單和可視化。

本文附件中包含了該插件和其源碼,讀者可以進行體驗和參考。請盡量閱讀該插件的完整代碼,這有助於您了解本文的內容。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved