樂在其中

          以JEE為主攻,以Flex為點綴,以Eclipse RCP為樂趣
          請訪問http://www.inframesh.org

          首頁 新隨筆 聯(lián)系 管理
            43 Posts :: 0 Stories :: 8 Comments :: 0 Trackbacks
          Dialog是SWT和JFace的一個重要的組成部分,我們在開發(fā)Plug-in或RCP的時候也經(jīng)常會用到它們。這篇隨筆不會介紹 SWT的Dialog,因為我想很多人都已經(jīng)非常熟悉它了。在這里,我要討論的是JFace的Dialog,或者更進一步說是JFace的 TitleAreaDialog。什么是TitleAreaDialog呢?想想我們常常用到的New XX Wizard就知道了。在我們創(chuàng)建一個Java Project或Class的時候,我們所使用的Wizard其實就是由TitleAreaDialog構(gòu)成的。這種Dialog有如下所示的 TitleArea和一個標準的Button Bar:

                
                                              正常的TitleArea                                                                                                               帶有錯誤信息的TitleArea


                                              標準的Button Bar

          這種GUI的表現(xiàn)力要比SWT的Dialog強很多,而且JFace為該 Dialog封裝了很多東西,這也使開發(fā)工作變得更加簡單,所以我極力推薦使用TitleAreaDialog。那么讓我們來看一個最基本的 TitleAreaDialog:

          import org.eclipse.jface.dialogs.IDialogConstants;
          import org.eclipse.jface.dialogs.TitleAreaDialog;
          import org.eclipse.swt.SWT;
          import org.eclipse.swt.graphics.Point;
          import org.eclipse.swt.layout.GridData;
          import org.eclipse.swt.widgets.Composite;
          import org.eclipse.swt.widgets.Control;
          import org.eclipse.swt.widgets.Shell;
          import org.jthin.jpssp.ide.configuration.Activator;

          public class MyTitleAreaDialog extends TitleAreaDialog {

              
          /**
               * Create the dialog
               * 
               * 
          @param parentShell
               */

              
          public MyTitleAreaDialog(Shell parentShell) {
                  
          super(parentShell);
              }

              
          /*
               * (non-Javadoc)
               * 
               * @see org.eclipse.jface.dialogs.TitleAreaDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
               */

              
          protected Control createDialogArea(Composite parent) {
                  Composite area = (Composite) 
          super.createDialogArea(parent);
                  Composite container = 
          new Composite(area, SWT.NONE);
                  container.setLayoutData(
          new GridData(GridData.FILL_BOTH));

                  
          // TitleArea中的Title
                  setTitle("My TitleAreaDialog");

                  
          // TitleArea中的Message
                  setMessage("This is a simple TitleAreaDialog example.");

                  // TitleArea中的Image
                  setTitleImage(ResourceManager.getPluginImage(Activator.getDefault(), "icons/Neptune.png"));

                  
          return area;
              }

              
          /*
               * (non-Javadoc)
               * 
               * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
               */

              
          protected void createButtonsForButtonBar(Composite parent) {
                  createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
          true);
                  createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, 
          false);
              }

              
          /*
               * (non-Javadoc)
               * 
               * @see org.eclipse.jface.dialogs.TitleAreaDialog#getInitialSize()
               */

              
          protected Point getInitialSize() {
                  
          return new Point(500, 375);
              }

              
          /*
               * (non-Javadoc)
               * 
               * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
               */

              
          protected void configureShell(Shell newShell) {
                  
          super.configureShell(newShell);

                  
          // Dialog Title
                  newShell.setText("Test TitleAreaDialog Title");

                  
          // Dialog Icon
                  newShell.setImage(ResourceManager.getPluginImage(Activator.getDefault(), "icons/Neptune.png"));
              }

          }

          這段代碼非常容易理解,從方法簽名中可以看出每個方法做了什么事情。注意createButtonsForButtonBar方法,其中用createButton方法創(chuàng)建了OK和Cancel這兩個Button,并且把Button的默認點擊事件也寫好了,就是關(guān)閉該 Dialog。ResourceManager.getPluginImage是我自己編寫的獲得圖片的helper method,這里就不討論其實現(xiàn)了。這段代碼會產(chǎn)生如下的Dialog:



          有趣的是,我在這里故意使用了一個128×128的大圖標, TitleAreaDialog不會自動縮小或裁減Image,而是調(diào)整TitleArea的大小來適應(yīng)Image。

          接下來我們要為OK Button編寫我們自己的事件,例如把用戶在Dialog中的輸入保存到某處。有人可能會想到為OK Button添加SelectionListener,但實際上這樣做是不對的,因為OK Button是JFace為Dialog封裝好了的,同時JFace也提供了響應(yīng)的callback:

          /*
           * (non-Javadoc)
           * 
           * @see org.eclipse.jface.dialogs.Dialog#okPressed()
           
          */
          protected void okPressed() {
             
          // implement your own function here
              super.okPressed();
          }

          我們可以在這里實現(xiàn)我們自己的事件,不過最后一定要調(diào)用super.okPressed方法,否則Dialog就不會關(guān)閉了。

          OK,以上就是TitleAreaDialog的基本Framework,非常容易理解,下面我們就來在 TitleArea中動態(tài)設(shè)置一些信息。你可以把這個scenario想象成在用戶輸入的同時提示用戶輸入的合法性。TitleAreaDialog提供了好3個方法可以動態(tài)設(shè)置TitleArea信息,具體如下:
          • public void setErrorMessage(String newErrorMessage):顯示傳入的錯誤信息。(我們把用這個方法設(shè)置的信息叫做error message。)當前顯示的信息會被保存起來,等到error message清空之后會再次顯示,而清空error message要傳入null,而不是傳入空字符串。
          • setMessage(String newMessage):顯示傳入的信息,等同于setMessage(String newMessage, IMessageProvider.NONE)。如果當前顯示的是error message,那么newMessage會被保存起來,等到error message清空后再顯示。
          • setMessage(String newMessage, int newType):顯示傳入的信息,并顯示指定的信息類型。可用的類型有NONE、INFORMATION、WARNING和ERROR。需要注意的是, setMessage(String newMessage, int IMessageProvider.ERROR)和setErrorMessage(String newErrorMessage)并不相同。后者會覆蓋當前的任何信息,而前者只會覆蓋當前的非error message,不會影響到error message(也就是說當error message清空后才會顯示)。
          這樣,我們就可以為一些文本框添加ModifyListener,然后在其中設(shè)置TitleArea的信息了。

          接著,再讓我們來看看Button Bar。有些時候,我們希望把OK和Cancel這種默認的Button放置在Button Bar的右側(cè),而把其他Button放置在Button Bar的左側(cè),如下圖中的Customize... Button:



          這又如何實現(xiàn)呢?有人可能想到在 createButtonsForButtonBar方法中做一些手腳,但是遺憾的是這行不通,我們真正要覆寫的是createButtonBar方法,下面是一個簡單的例子:

          /*
           * (non-Javadoc)
           * 
           * @see org.eclipse.jface.dialogs.TrayDialog#createButtonBar(org.eclipse.swt.widgets.Composite)
           
          */
          protected Control createButtonBar(Composite parent) {
              Composite composite 
          = new Composite(parent, SWT.NONE);
              GridLayout layout 
          = new GridLayout();
              layout.numColumns 
          = 0;
              layout.marginHeight 
          = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
              layout.marginWidth 
          = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
              layout.verticalSpacing 
          = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
              layout.horizontalSpacing 
          = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);

              composite.setLayout(layout);
              composite.setLayoutData(
          new GridData(GridData.FILL_HORIZONTAL));

             
          if (isHelpAvailable()) {
                  createHelpControl(composite);
              }

              createButton(composite, MyConstants.IMPORT_BUTTON_ID, 
          "Import", false).addSelectionListener(new SelectionAdapter() {
                 
          public void widgetSelected(SelectionEvent e) {
                      MessageDialog.openInformation(MaintainModuleDialog.
          this.getShell(), "Information",
                         
          "\"Import\" button has not been implemented.");
                  }
              });

              createButton(composite, MyConstants.EXPORT_BUTTON_ID, 
          "Export", false).addSelectionListener(new SelectionAdapter() {
                 
          public void widgetSelected(SelectionEvent e) {
                      MessageDialog.openInformation(MaintainModuleDialog.
          this.getShell(), "Information",
                     
          "\"Export\" button has not been implemented.");
                  }
              });

              createButton(composite, MyConstants.OTHER_BUTTON_ID, 
          "Other"false).addSelectionListener(new SelectionAdapter() {
             
              public void widgetSelected(SelectionEvent e) {
                      MessageDialog.openInformation(MaintainModuleDialog.
          this.getShell(), "Information",
                     
          "\"Other\" button has not been implemented.");
                  }
              });

              Label filler 
          = new Label(composite, SWT.NONE);
              filler.setLayoutData(
          new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
              layout.numColumns
          ++;

             
          super.createButtonsForButtonBar(composite);

             
          return composite;
          }

          正如你所見,我們實際上創(chuàng)建了自己的Button Bar,然后在上面添加了3個Button:Import、Export和Other,最后 super.createButtonsForButtonBar會創(chuàng)建OK和Cancel Button。filler是用來在兩組Button見占位的。代碼中用到的兩個convert方法來自 org.eclipse.jface.dialogs.Dialog類,你還可以在這個類中找到一個getButton(int)方法,它可以根據(jù)傳入的 ID返回用createButton創(chuàng)建的Button。這些都是非常實用的方法。

          回頭看一下上面那個完整的 TitleAreaDialog圖片,你會看到在Dialog左下角有一個問號符號,這其實是一個Button,點擊它可以顯示幫助信息,當然幫助信息是由你來創(chuàng)建的。讓我們看看Eclipse Search的TitleAreaDialog中的幫助信息吧:



          如果我們也想實現(xiàn)這種幫助機制,那么就要實現(xiàn)如下方法:

          /*
           * (non-Javadoc)
           * 
           * @see org.eclipse.jface.dialogs.TrayDialog#createHelpControl(org.eclipse.swt.widgets.Composite)
           
          */
          protected Control createHelpControl(Composite parent) {
              // TODO Auto-generated method stub
              return super.createHelpControl(parent);
          }

          如果不想實現(xiàn)幫助機制,那么最好不要在Dialog中顯示出那個問號符號,你可以覆寫如下方法并永遠返回false,這樣就不會顯示問號符號了。

          /*
           * (non-Javadoc)
           * 
           * @see org.eclipse.jface.dialogs.TrayDialog#isHelpAvailable()
           
          */

          public boolean isHelpAvailable() {
              return false;
          }

          那么這個酷酷的幫助機制到底是個什么東西呢?實際上,它的學(xué)名叫做DialogTray。TitleAreaDialog繼承了
          org.eclipse.jface.dialogs.TrayDialog類,而TrayDialog就可以顯示這種 DialogTray,是不是有點兒拗口呢?實際上,我們不僅僅可以添加幫助信息這一種DialogTray,還可以添加任意的DialogTray,現(xiàn)在就讓我們動手實現(xiàn)一個最簡單的吧。代碼很簡單,最主要的就是要實現(xiàn)一個DialogTray,代碼如下:

          import org.eclipse.jface.dialogs.DialogTray;
          import org.eclipse.swt.SWT;
          import org.eclipse.swt.layout.GridData;
          import org.eclipse.swt.layout.GridLayout;
          import org.eclipse.swt.widgets.Composite;
          import org.eclipse.swt.widgets.Control;
          import org.eclipse.swt.widgets.Label;
          import org.eclipse.swt.widgets.Text;

          public class MyDialogTray extends DialogTray {

              
          /*
               * (non-Javadoc)
               * 
               * @see org.eclipse.jface.dialogs.DialogTray#createContents(org.eclipse.swt.widgets.Composite)
               
          */
              
          protected Control createContents(Composite parent) {
                  Composite container 
          = new Composite(parent, SWT.NONE);
                  
          final GridLayout gridLayout = new GridLayout();
                  gridLayout.numColumns 
          = 2;
                  container.setLayout(gridLayout);

                  
          final Label label = new Label(container, SWT.NONE);
                  label.setText(
          "Name:");

                  
          final Text text = new Text(container, SWT.BORDER);
                  text.setLayoutData(
          new GridData(SWT.FILL, SWT.CENTER, truefalse));

                  
          return container;
              }

          }

          我們只在其中創(chuàng)建了一個Label和一個Text,這就足夠了。最后,我們?yōu)镸yTitleAreaDialog添加兩個Button,用來打開和關(guān)閉MyDialogTray,代碼如下:

          final Button openTrayButton = new Button(container, SWT.NONE);
          openTrayButton.setText(
          "Open Tray");

          final Button closeTrayButton = new Button(container, SWT.NONE);
          closeTrayButton.setText(
          "Close Tray");
          closeTrayButton.setEnabled(
          false);

          openTrayButton.addSelectionListener(
          new SelectionAdapter() {
              public void widgetSelected(final SelectionEvent e) {
                  // this method is from TrayDialog
                  openTray(new MyDialogTray());
                  openTrayButton.setEnabled(
          false);
                  closeTrayButton.setEnabled(
          true);
              }
          });

          closeTrayButton.addSelectionListener(
          new SelectionAdapter() {
             
          public void widgetSelected(final SelectionEvent e) {
                 
          // this method is from TrayDialog
                  closeTray();
                  openTrayButton.setEnabled(
          true);
                  closeTrayButton.setEnabled(
          false);
              }
          });

          最后我們會得到如下對話框:



          好了,就講這么多吧。如果能把這些東東適當?shù)赜迷谀愕腁pplication中,那么效果一定非常棒。
          posted on 2009-04-29 23:09 suprasoft Inc,. 閱讀(1930) 評論(1)  編輯  收藏 所屬分類: Eclipse

          Feedback

          # re: TitleAreaDialog/TrayDialog 2012-11-09 09:28 插件開發(fā)者
          打開 TitleAreaDialog 是調(diào)用open()方法。
          但是為什么是模式化窗口???
          有什么變量或?qū)傩?能夠改變成 單獨一個窗口呢???

          我不想要弄成 模式化窗口。  回復(fù)  更多評論
            

          ©2005-2008 Suprasoft Inc., All right reserved.
          主站蜘蛛池模板: 舒兰市| 昭平县| 府谷县| 丘北县| 临西县| 明水县| 杭州市| 河源市| 汝州市| 远安县| 集安市| 岳普湖县| 枣强县| 武隆县| 城口县| 颍上县| 黄骅市| 永福县| 天台县| 贡嘎县| 太和县| 油尖旺区| 班玛县| 汤原县| 威远县| 翼城县| 鄢陵县| 乃东县| 介休市| 汤原县| 铁岭市| 井冈山市| 太和县| 彭泽县| 兴化市| 巴林右旗| 嵊州市| 泾源县| 当雄县| 华容县| 翁源县|