gembin

          OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

          HBase, Hadoop, ZooKeeper, Cassandra

          Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

          There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

          About Me

           

          在定制 SWT 組件中實現 MVC

          Eclipse SWT(標準部件工具包)提供了豐富的 API 集來實現定制部件(widget)。在這篇文章中,作者簡要概括了 MVC(模型-視圖-控制器)架構,以結構化查看器的形式解釋了 MVC 的當前實現,并介紹了一種使用定制 SWT 部件的實現。

          什么是 MVC?

          MVC 架構(或設計模式)是圖形用戶界面(GUI)的設計樣式,由三部分構成:模型、視圖和控制器。MVC 把表示層從數據解耦出來,也把表示從數據的操作解耦出來。

          實現 MVC 架構與其他類型的應用程序有所不同。主要的區別來自如何放置和實現業務邏輯或查看呈現邏輯。與典型的 Web 應用程序不同,在這類程序中,程序員必須設計和實現所有 MVC 組件,而 Eclipse 提供的 API 可以替您做大部分控制或呈現工作。所以,不能嚴格地把 Eclipse 的 MVC 實現與 Web 或其他應用程序類型的 MVC 進行比較。


          Eclipse JFace

          Eclipse JFace 用內容提供者和標簽提供者實現 MVC 架構。JFace API 包裝了標準(并非不重要的)部件,例如表和樹,并實現了結構化內容提供者和標簽提供者。可以根據部件類型實現不同的內容提供者。面向列表的查看器會實現結 構化查看器,而內容則以結構化(列表的)方式映射到部件條目上。

          基類叫做 Viewer,它是結構化查看器的一個擴展。查看器充當部件容器。內容提供者以結構化的方式得到數據;類似地,標簽提供者獲得對應的標簽。JFace 查看器實現檢索該數據,設置對應的關聯,并用數據集更新用戶界面(UI)組件。它還執行選擇、過濾和排序。


          如何實現 JFace

          Eclipse ViewViewer 負責執行大部分 JFace 控制功能。Viewer 或者說 MVC 的視圖部分,也充當部件容器;這是表示組件。

          Eclipse View 實例化 Viewer、內容提供者和標簽提供者,并充當模型,容納值對象,并在 Viewer 中把它們設置為 inputElement

          要創建 View,請用 createPartControl() 方法實例化 Viewer清單 1 實例化一個默認的樹查看器;您也可以定制樹,并用樹對象作為參數,用構造函數實例化樹查看器。


          清單 1. ExampleView 的 CreatePartControl 方法
          public class ExampleView extends ViewPart 
          { ... public void createPartControl(Composite parent)
          { // define a grid layout
          GridLayout layout = new GridLayout();
          layout.numColumns = 1;
          layout.marginHeight = 0;
          layout.marginWidth = 0; l
          ayout.horizontalSpacing = 0;
          layout.verticalSpacing = 1;
          parent.setLayout(layout);
          // create widgets createActionBar(parent);
          createTree(parent);
          // add context menu and listeners
          viewer.addDoubleClickListener(this); viewer.addSelectionChangedListener(openAction);
          // register viewer so actions respond to selection getSite().setSelectionProvider(viewer);
          hookContextMenu();
          }
          private void createTree(Composite parent)
          {
          viewer = new TreeViewer(parent, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
          viewer.setContentProvider(new ExampleViewContentProvider()); viewer.setLabelProvider
          (new ExampleViewLabelProvider());
          viewer.setSorter(new ViewerSorter());
          viewer.setInput(ModelManager.getExampleModel());
          viewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH));
          } ... }

          在另一個獨立類中實現 ContentProvider,它是一個對象,用適合查看器類型的接口向視圖提供數據。例如,您可以實現 IStructuredContentProviderITreeContentProvider 查看器。

          請在 ContentProvider 代碼中實現以下一個方法,把 ContentProviderViewer 相關聯:

          • getElements(Object parent)
          • getChildren(Object element)

          注意:JFace 框架將調用這些方法。


          清單 2. 創建定制的 ContentProvider
            public class ExampleViewContentprovide implements ITreeContentProvide {

          MVC 架構通常包含多個視圖和一個數據源。目前在 Eclipse 平臺上,只能把一個視圖與一個模型相關聯。但是,也可以創建多個視圖,用適配器視圖訪問同一數據。只要把 inputChanged() 方法包含在 ContentProvider 類中即可。只要 Viewer 有新的輸入集,就會使用 inputChanged() 方法通知 ContentProviderinputChanged() 方法接受 Viewer 作為輸入參數,所以多個視圖可以使用一個 ContentProvider


          清單 3. 將 inputChanged 方法用于不同的查看器
          /** * Register content provider with model. */
          public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
          {
          if (newInput != null)
          {
          this.viewer = viewer;
          this.model = (ExampleDelegate)newInput; this.model.addModelListener(this);
          }
          }


          與 Eclipse SWT 結合使用 MVC

          在多數常見 GUI 應用程序中,創建布局來顯示請求的數據,或完成表單(例如用戶界面)來添加或修改數據。圖 1 的示例應用程序演示了如何在定制表單中,用只讀和可編寫模式顯示來自 XML 存儲的數據。它還解釋了每個組件相對于 MVC 架構的角色。


          圖 1. 示例應用程序
          示例應用程序截屏

          圖 2 顯示了應用程序的類圖,有助于更好地理解整體架構。


          圖 2. 示例應用程序的類圖
          示例應用程序的類圖


          創建控件

          ExampleView 充當整個應用程序的容器。它將在 createPartControl 方法中初始化應用程序。


          清單 4. CreatePartControl 方法初始化布局
          public void createPartControl(Composite parent) {
          ExampleEditLayout _layout = new
          ExampleEditLayout(parent,SWT.NONE,FieldMode.Read,new ExampleViewContentProvider());
          }


          創建表單和布局

          基本布局類定義了不同的表單應用程序使用的全局方法和聲明。有些充當回調機制的容器事件,也注冊到了這里。


          清單 5. 布局的 CreateControl 方法
          public void createControls(int style) {
          GridData gridData;
          Text textFld, subjectFld;
          Control toLabel, ccLabel, bccLabel;
          Control fromDateTime;
          Control control;
          Button durationText;
          Button submit;
          GridLayout layout = new GridLayout(2, false);
          layout.marginWidth = 0;
          layout.marginHeight = 4;
          setLayout(layout);
          //Label
          gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL
          | GridData.VERTICAL_ALIGN_CENTER);
          gridData.horizontalIndent = 10;
          LabelFactory.create(this,
          Messages.getString("ExampleEditLayout.Title"), gridData); //$NON-NLS-1$
          gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL
          | GridData.VERTICAL_ALIGN_CENTER);
          gridData.horizontalIndent = 40;
          LabelFactory.create(this, "", gridData);
          //Text
          gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL
          | GridData.VERTICAL_ALIGN_CENTER);
          gridData.horizontalIndent = 10;
          control = LabelFactory.create(this,
          Messages.getString("ExampleEditLayout.Email"), gridData); //$NON-NLS-1$
          gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING
          | GridData.VERTICAL_ALIGN_CENTER);
          gridData.horizontalIndent = 10;
          control = TextFactory.create(this,
          SWT.BORDER | SWT.V_SCROLL | SWT.WRAP, gridData, FieldMode.Edit); //$NON-NLS-1$
          addField(new TextField(control, ExampleViewContentProvider.FIRST_INDEX));
          //Combo
          gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL
          | GridData.VERTICAL_ALIGN_CENTER);
          gridData.horizontalIndent = 10;
          LabelFactory.create(this,
          Messages.getString("ExampleEditLayout.Group"), gridData); //$NON-NLS-1$
          gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING
          | GridData.VERTICAL_ALIGN_CENTER);
          gridData.horizontalIndent = 40;
          control = ComboFactory.create(this,
          FieldMode.Edit, false, gridData); //$NON-NLS-1$
          addField(new ComboField(control,
          ExampleViewContentProvider.SECOND_INDEX));
          ...}


          創建字段(視圖)

          Field 是一個抽象類,它定義了包含各種用戶界面控件的方法,還有全局地識別這些控件的相關 ID。每個用戶界面控件都是 Field 的子類,并向內容提供者提供了讀寫能力。清單 6 用工廠模式,在 Layout 類中創建了 Field


          清單 6. 用 Field 類創建文本對象
          public class TextField extends Field {
          /**
          * @param control
          * @param id
          */
          public TextField(Control control, int id) {
          super(control, id);
          }
          /* Based on the ID of the widget, values retrieved from
          * the content provider are set.
          */
          public void readFromContent(IExampleContentProvider content) {
          String newText = (String )content.getElement(getId());
          if (newText != null)
          ((Text )_control).setText(newText);
          }
          /* Based on the ID of the widget, values retrieved from widget are
          * sent back to the content provider.
          */
          public void writeToContent(IExampleContentProvider content) {
          String newText = ((Text )_control).getText();
          content.setElement(getId(), newText);
          }
          }


          簡化內容提供者(模型)

          ExampleViewContentProvider 充當模型偵聽器,后者擴展自 IStructuredContentProvider。它是 Eclipse API 的簡單實現,提供了用于檢索數據的回調。每個請求數據的條目都基于視圖創建時在布局中為條目定義的惟一 ID。

          方法調用會返回與每個定義的全局 ID 關聯的數據。在 清單 7 所示的內容提供者中,可以使用適配器從 XML 文件或數據庫檢索數據。


          清單 7. 在定制的 ContentProvider 中實現方法
          public Object getElement(int iIndex) {
          switch (iIndex) {
          case FIRST_INDEX: return "developer@ibm.com";
          case SECOND_INDEX : return new Integer(1);
          case FOURTH_INDEX : return new Boolean(true);
          case THIRD_INDEX: return new Boolean(false);
          case FIFTH_INDEX: return new Boolean(false);
          }
          return null;
          }

          創建了控件并初始化布局之后,表單會用控件 ID 要求內容提供者用數據填充表單控件。


          清單 8. 初始化布局并填充控件的表單
          public Form (Composite parent, int style, FieldMode mode, ExampleViewContentProvider content) {
          super(parent, style);
          _content = content;
          _style = style;
          setMode(mode);
          init(style);
          }

          private void init(int style) {
          createControls(style);
          controlsCreated();
          }
          protected void controlsCreated() {
          readFromContent();
          }



          結束語

          Web 應用程序是 MVC 架構樣式的早期實現者。但是,隨著像 Eclipse 這樣的簡單而強大的開發平臺的到來,程序員可以輕易地用更短的時間和最小的復雜程度,開發出更豐富的用戶界面。




          下載

          描述名字大小下載方法
          Example code for this article wa-eclipsemvc_ExampleViewer.zip 33KB HTTP

          posted on 2008-03-19 18:06 gembin 閱讀(970) 評論(1)  編輯  收藏 所屬分類: Eclipse RCPSWT

          評論

          # re: 在定制 SWT 組件中實現 MVC 2008-03-20 10:51 klzz

          好文章要頂!!!  回復  更多評論   

          導航

          統計

          常用鏈接

          留言簿(6)

          隨筆分類(440)

          隨筆檔案(378)

          文章檔案(6)

          新聞檔案(1)

          相冊

          收藏夾(9)

          Adobe

          Android

          AS3

          Blog-Links

          Build

          Design Pattern

          Eclipse

          Favorite Links

          Flickr

          Game Dev

          HBase

          Identity Management

          IT resources

          JEE

          Language

          OpenID

          OSGi

          SOA

          Version Control

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          free counters
          主站蜘蛛池模板: 泸溪县| 济源市| 恩施市| 钟山县| 鄂伦春自治旗| 崇仁县| 娄烦县| 乐陵市| 桃园县| 宁远县| 垫江县| 阿合奇县| 房产| 富蕴县| 石柱| 贵德县| 那曲县| 渭源县| 大渡口区| 洛宁县| 高安市| 寻甸| 五指山市| 罗田县| 龙江县| 大厂| 登封市| 阿拉善左旗| 新闻| 胶州市| 武功县| 新巴尔虎左旗| 阜城县| 平湖市| 连州市| 隆安县| 宣恩县| 增城市| 广州市| 潢川县| 南川市|