在定製Eclipse SWT組件中實現MVC

來源:互聯網
上載者:User
  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 View 和 Viewer 負責執行大部分 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,它是一個對象,用適合查看器類型的介面向視圖提供資料。例如,您可以實現 IStructuredContentProvider 或 ITreeContentProvider 查看器。

  請在 ContentProvider 代碼中實現以下一個方法,把 ContentProvider 與 Viewer 相關聯:
  • getElements(Object parent)
  • getChildren(Object element)

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

  清單 2. 建立定製的 ContentProvider

    public class ExampleViewContentprovide implements ITreeContentProvide {  

  MVC 架構通常包含多個視圖和一個資料來源。目前在 Eclipse 平台上,只能把一個視圖與一個模型相關聯。但是,也可以建立多個視圖,用適配器視圖訪問同一資料。只要把 inputChanged() 方法包含在 ContentProvider 類中即可。只要 Viewer 有新的輸入集,就會使用 inputChanged() 方法通知 ContentProvider。inputChanged() 方法接受 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 是一個抽象類別,它定義了包含各種使用者介面控制項的方法,還有全域地識別這些控制項的相互關聯識別碼。每個使用者介面控制項都是 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。

  方法調用會返回與每個定義的全域識別碼 關聯的資料。在 清單 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 這樣的簡單而強大的開發平台的到來,程式員可以輕易地用更短的時間和最小的複雜程度,開發出更豐富的使用者介面。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.