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 組件中實(shí)現(xiàn) MVC

          Eclipse SWT(標(biāo)準(zhǔn)部件工具包)提供了豐富的 API 集來(lái)實(shí)現(xiàn)定制部件(widget)。在這篇文章中,作者簡(jiǎn)要概括了 MVC(模型-視圖-控制器)架構(gòu),以結(jié)構(gòu)化查看器的形式解釋了 MVC 的當(dāng)前實(shí)現(xiàn),并介紹了一種使用定制 SWT 部件的實(shí)現(xiàn)。

          什么是 MVC?

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

          實(shí)現(xiàn) MVC 架構(gòu)與其他類型的應(yīng)用程序有所不同。主要的區(qū)別來(lái)自如何放置和實(shí)現(xiàn)業(yè)務(wù)邏輯或查看呈現(xiàn)邏輯。與典型的 Web 應(yīng)用程序不同,在這類程序中,程序員必須設(shè)計(jì)和實(shí)現(xiàn)所有 MVC 組件,而 Eclipse 提供的 API 可以替您做大部分控制或呈現(xiàn)工作。所以,不能嚴(yán)格地把 Eclipse 的 MVC 實(shí)現(xiàn)與 Web 或其他應(yīng)用程序類型的 MVC 進(jìn)行比較。


          Eclipse JFace

          Eclipse JFace 用內(nèi)容提供者和標(biāo)簽提供者實(shí)現(xiàn) MVC 架構(gòu)。JFace API 包裝了標(biāo)準(zhǔn)(并非不重要的)部件,例如表和樹,并實(shí)現(xiàn)了結(jié)構(gòu)化內(nèi)容提供者和標(biāo)簽提供者。可以根據(jù)部件類型實(shí)現(xiàn)不同的內(nèi)容提供者。面向列表的查看器會(huì)實(shí)現(xiàn)結(jié) 構(gòu)化查看器,而內(nèi)容則以結(jié)構(gòu)化(列表的)方式映射到部件條目上。

          基類叫做 Viewer,它是結(jié)構(gòu)化查看器的一個(gè)擴(kuò)展。查看器充當(dāng)部件容器。內(nèi)容提供者以結(jié)構(gòu)化的方式得到數(shù)據(jù);類似地,標(biāo)簽提供者獲得對(duì)應(yīng)的標(biāo)簽。JFace 查看器實(shí)現(xiàn)檢索該數(shù)據(jù),設(shè)置對(duì)應(yīng)的關(guān)聯(lián),并用數(shù)據(jù)集更新用戶界面(UI)組件。它還執(zhí)行選擇、過(guò)濾和排序。


          如何實(shí)現(xiàn) JFace

          Eclipse ViewViewer 負(fù)責(zé)執(zhí)行大部分 JFace 控制功能。Viewer 或者說(shuō) MVC 的視圖部分,也充當(dāng)部件容器;這是表示組件。

          Eclipse View 實(shí)例化 Viewer、內(nèi)容提供者和標(biāo)簽提供者,并充當(dāng)模型,容納值對(duì)象,并在 Viewer 中把它們?cè)O(shè)置為 inputElement

          要?jiǎng)?chuàng)建 View,請(qǐng)用 createPartControl() 方法實(shí)例化 Viewer清單 1 實(shí)例化一個(gè)默認(rèn)的樹查看器;您也可以定制樹,并用樹對(duì)象作為參數(shù),用構(gòu)造函數(shù)實(shí)例化樹查看器。


          清單 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));
          } ... }

          在另一個(gè)獨(dú)立類中實(shí)現(xiàn) ContentProvider,它是一個(gè)對(duì)象,用適合查看器類型的接口向視圖提供數(shù)據(jù)。例如,您可以實(shí)現(xiàn) IStructuredContentProviderITreeContentProvider 查看器。

          請(qǐng)?jiān)?ContentProvider 代碼中實(shí)現(xiàn)以下一個(gè)方法,把 ContentProviderViewer 相關(guān)聯(lián):

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

          注意:JFace 框架將調(diào)用這些方法。


          清單 2. 創(chuàng)建定制的 ContentProvider
            public class ExampleViewContentprovide implements ITreeContentProvide {

          MVC 架構(gòu)通常包含多個(gè)視圖和一個(gè)數(shù)據(jù)源。目前在 Eclipse 平臺(tái)上,只能把一個(gè)視圖與一個(gè)模型相關(guān)聯(lián)。但是,也可以創(chuàng)建多個(gè)視圖,用適配器視圖訪問(wèn)同一數(shù)據(jù)。只要把 inputChanged() 方法包含在 ContentProvider 類中即可。只要 Viewer 有新的輸入集,就會(huì)使用 inputChanged() 方法通知 ContentProviderinputChanged() 方法接受 Viewer 作為輸入?yún)?shù),所以多個(gè)視圖可以使用一個(gè) 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 結(jié)合使用 MVC

          在多數(shù)常見(jiàn) GUI 應(yīng)用程序中,創(chuàng)建布局來(lái)顯示請(qǐng)求的數(shù)據(jù),或完成表單(例如用戶界面)來(lái)添加或修改數(shù)據(jù)。圖 1 的示例應(yīng)用程序演示了如何在定制表單中,用只讀和可編寫模式顯示來(lái)自 XML 存儲(chǔ)的數(shù)據(jù)。它還解釋了每個(gè)組件相對(duì)于 MVC 架構(gòu)的角色。


          圖 1. 示例應(yīng)用程序
          示例應(yīng)用程序截屏

          圖 2 顯示了應(yīng)用程序的類圖,有助于更好地理解整體架構(gòu)。


          圖 2. 示例應(yīng)用程序的類圖
          示例應(yīng)用程序的類圖


          創(chuàng)建控件

          ExampleView 充當(dāng)整個(gè)應(yīng)用程序的容器。它將在 createPartControl 方法中初始化應(yīng)用程序。


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


          創(chuàng)建表單和布局

          基本布局類定義了不同的表單應(yīng)用程序使用的全局方法和聲明。有些充當(dāng)回調(diào)機(jī)制的容器事件,也注冊(cè)到了這里。


          清單 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));
          ...}


          創(chuàng)建字段(視圖)

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


          清單 6. 用 Field 類創(chuàng)建文本對(duì)象
          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);
          }
          }


          簡(jiǎn)化內(nèi)容提供者(模型)

          ExampleViewContentProvider 充當(dāng)模型偵聽(tīng)器,后者擴(kuò)展自 IStructuredContentProvider。它是 Eclipse API 的簡(jiǎn)單實(shí)現(xiàn),提供了用于檢索數(shù)據(jù)的回調(diào)。每個(gè)請(qǐng)求數(shù)據(jù)的條目都基于視圖創(chuàng)建時(shí)在布局中為條目定義的惟一 ID。

          方法調(diào)用會(huì)返回與每個(gè)定義的全局 ID 關(guān)聯(lián)的數(shù)據(jù)。在 清單 7 所示的內(nèi)容提供者中,可以使用適配器從 XML 文件或數(shù)據(jù)庫(kù)檢索數(shù)據(jù)。


          清單 7. 在定制的 ContentProvider 中實(shí)現(xiàn)方法
          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;
          }

          創(chuàng)建了控件并初始化布局之后,表單會(huì)用控件 ID 要求內(nèi)容提供者用數(shù)據(jù)填充表單控件。


          清單 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();
          }



          結(jié)束語(yǔ)

          Web 應(yīng)用程序是 MVC 架構(gòu)樣式的早期實(shí)現(xiàn)者。但是,隨著像 Eclipse 這樣的簡(jiǎn)單而強(qiáng)大的開(kāi)發(fā)平臺(tái)的到來(lái),程序員可以輕易地用更短的時(shí)間和最小的復(fù)雜程度,開(kāi)發(fā)出更豐富的用戶界面。




          下載

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

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

          評(píng)論

          # re: 在定制 SWT 組件中實(shí)現(xiàn) MVC 2008-03-20 10:51 klzz

          好文章要頂!!!  回復(fù)  更多評(píng)論   

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(6)

          隨筆分類(440)

          隨筆檔案(378)

          文章檔案(6)

          新聞檔案(1)

          相冊(cè)

          收藏夾(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

          最新隨筆

          搜索

          積分與排名

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          free counters
          主站蜘蛛池模板: 江西省| 贡山| 察雅县| 巫溪县| 孟津县| 监利县| 河西区| 同仁县| 石棉县| 临城县| 平果县| 城固县| 宿州市| 怀集县| 阿鲁科尔沁旗| 朝阳区| 怀宁县| 上杭县| 揭阳市| 永城市| 中江县| 开阳县| 蒙城县| 富裕县| 芮城县| 赤水市| 新泰市| 嘉善县| 定州市| 株洲县| 临江市| 思茅市| 武宁县| 手机| 仁化县| 五峰| 大余县| 荥经县| 晋宁县| 永清县| 铁岭县|