本例將給視圖加入下拉菜單和按鈕,同時再為列表添加一個右鍵菜單.
創建ActionGroup類
加入菜單和按鈕的方法與SWT和JFace組件的一樣,先創建一個ActionGroup代碼如下:
MyActionGroup.java
1 public class MyActionGroup extends ActionGroup { 2 // 加入按鈕 3 public void fillActionBars(IActionBars actionBars) { 4 if (actionBars == null) 5 return; 6 IToolBarManager toolBar = actionBars.getToolBarManager(); 7 toolBar.add(new Action1()); 8 toolBar.add(new Action2()); 9 } 10 11 // 加入下拉菜單、右鍵彈出菜單 12 public void fillContextMenu(IMenuManager menu) { 13 if (menu == null) 14 return; 15 menu.add(new Action1()); 16 menu.add(new Action2()); 17 } 18 19 private class Action1 extends Action { 20 public Action1() { 21 ImageDescriptor imageDesc = WorkbenchImages 22 .getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_NEW_PAGE); 23 //.getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_HOME_NAV); 24 //這個地放原碼是想在在View1上顯示一個"小房子"的圖標.但是我參看IWorkbenchGraphicConstants的源碼 25 //沒有IMG_ETOOL_HOME_NAV這個常量字段.導入Eclipse也報錯,我就 換了一個. 26 setHoverImageDescriptor(imageDesc); 27 setText("Action1"); 28 } 29 30 public void run() { 31 } 32 } 33 34 private class Action2 extends Action { 35 public Action2() { 36 ImageDescriptor imageDesc = WorkbenchImages 37 .getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_IMPORT_WIZ); 38 setHoverImageDescriptor(imageDesc); 39 setText("Action2"); 40 } 41 42 public void run() { 43 new LanguageDialog(null).open(); 44 } 45 } 46 }
程序說明:
1.本程序中含有兩個Action類:Action1,Action2,和以往的Action不同之處在於它的圖像描述符是直接從Eclipse環境中取得.既然插件在Eclipse環境內運行,那么Eclipse本身的圖標就可以直接拿來使用,不過Eclipse會給出 一個警告:"建議不要訪問:由於對必須的庫...jar 具有一定的限制,一次不能訪問類型WorkbenchImages",這是因為該類internal包中,也就是說它僅局限於內部使用.
2.fillContextMenu方法比起以前單純的SWT編程少了幾句.在后邊的總結在紅中可以看到它移動到View1類中去了,主要原因是為了此方法兼顧添加視圖的下拉菜單.
修改View1類
在Viwe1中增加了3中方法,分別用來加入視圖的導航欄按鈕,下拉菜單,以及加入表List的右鍵菜單.代碼如下:
(下面的這個View1.java中也加入了編輯器對應的事件.雙擊視圖1的列表項,則打開對應的編輯器,因此在View1類的List對象添加一個鼠標雙擊視圖1的列表項,則打開對應的編輯器,一次在View1類的List對象添加一個鼠標雙擊事件監聽器.另外還要考慮到,如果已經打開了列表項對應的編輯器,則下次再雙擊時就不應再打開該項的編輯器,而是將其設成當前編輯器.)
得到編輯器對象:IEditorPart editor = IWorkbenchPage.findEditor(IEditorInput);
打開編輯器對象:IWorkbenchpage.openEditor(IEditorInput.editorID);
View1.java
public class View1 extends ViewPart { private List list; // 將列表寫成類的實例變量,以擴大它的可訪問范圍 //注意這個List並不是java.util包下的.而是org.eclipse.swt.widgets.List;包下的. public void createPartControl(Composite parent) { IWorkbenchHelpSystem help = PlatformUI.getWorkbench().getHelpSystem(); help.setHelp(parent, "cn.com.kxh.myplugin.buttonHelpId"); Composite topComp = new Composite(parent, SWT.NONE); topComp.setLayout(new FillLayout()); list = new List(topComp, SWT.BORDER); list.add("中國"); list.add("美國"); list.add("法國"); // 列表選擇事件監聽 list.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { // 由IWorkbenchPage獲得view2對象 IWorkbenchPage wbp = getViewSite().getPage(); //在插件中IWorkbenchPage對象比較重要,這里再給出一種獲得此對象的通用的方法. // Activator.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage(); IViewPart view2 = wbp.findView("cn.com.kxh.myplugin.View2"); //這個地方的參數是"視圖2"在plugin.xml中的id標識.由此可見plugin.xml文件在插件中的地位是極其重要的. // 將當前選擇的列表項顯示在文本框中 Text text = ((View2) view2).getText(); text.setText(list.getSelection()[0]); } }); // 列表選擇事件監聽 list.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { // 由IWorkbenchPage獲得view2對象 IWorkbenchPage wbp = getViewSite().getPage();// Activator.getDefault().getWorkbench().getActiveWorkbenchWindow(). getActivePage(); IViewPart view2 = wbp.findView("cn.com.kxh.myplugin.View2"); // 將當前選擇的列表項顯示在文本框中 Text text = ((View2) view2).getText(); text.setText(list.getSelection()[0]); } }); list.addMouseListener(new MouseAdapter() { private ChinaEditorInput chinaEditorInput = new ChinaEditorInput(); private UsaEditorInput usaEditorInput = new UsaEditorInput(); private FranceEditorInput franceEditorInput = new FranceEditorInput(); public void mouseDoubleClick(MouseEvent e) { // 根據不同列表項得到其相應的editorInput對象和editorID,其中 // editorID指該編輯器在plugin.xml文件中設置id標識值 List list = (List) e.getSource();// 由MouseEvent得到列表對象 String listStr = list.getSelection()[0];// 得到當前列表項的字符 IEditorInput editorInput = null; String editorID = null; if (listStr.equals("中國")) { editorInput = chinaEditorInput; editorID = "cn.com.kxh.myplugin.ChinaEditor"; } else if (listStr.equals("美國")) { editorInput = usaEditorInput; editorID = "cn.com.kxh.myplugin.UsaEditor"; } else if (listStr.equals("法國")) { editorInput = franceEditorInput; editorID = "cn.com.kxh.myplugin.FranceEditor"; } // 如果editorInput或editorID為空則中斷返回 if (editorInput == null || editorID == null) return; // 取得IWorkbenchPage,並搜索使用editorInput對象對應的編輯器 IWorkbenchPage workbenchPage = getViewSite().getPage(); IEditorPart editor = workbenchPage.findEditor(editorInput); // 如果此編輯器已經存在,則將它設為當前的編輯器(最頂端),否則 // 重新打開一個編輯器 if (editor != null) { workbenchPage.bringToTop(editor); } else { try { workbenchPage.openEditor(editorInput, editorID); } catch (PartInitException e2) { e2.printStackTrace(); } } } }); // 加入導航欄按鈕、下拉菜單、右鍵菜單 MyActionGroup actionGroup = new MyActionGroup(); fillViewAction(actionGroup);// 加入視圖的導航欄按鈕 fillViewMenu(actionGroup);// 加入視圖的下拉菜單 fillListMenu(actionGroup);// 加入視圖的下拉菜單 } // 加入視圖的導航欄按鈕 private void fillViewAction(MyActionGroup actionGroup) { IActionBars bars = getViewSite().getActionBars(); actionGroup.fillActionBars(bars); } // 加入視圖的下拉菜單 private void fillViewMenu(MyActionGroup actionGroup) { IMenuManager manager = getViewSite().getActionBars().getMenuManager(); actionGroup.fillContextMenu(manager); } // 加入列表List的右鍵菜單 private void fillListMenu(MyActionGroup actionGroup) { MenuManager manger = new MenuManager(); Menu menu = manger.createContextMenu(list); list.setMenu(menu); actionGroup.fillContextMenu(manger); } @Override public void setFocus() {} }
程序說明:視圖加按鈕,菜單的方式和以前SWT的方式是一樣的,只不過以前自己生成MenuManager等對象,而現在只需要使用插件平台提供的MenuManager對象.
在事件處理方法:本程序中為了便於理解,使用了if...else這種簡單的方式來判斷被雙擊的類表項,這適合列表項較少的情況,如果列表項太多,則代碼會相當長.解決這個問題,可將IEditorInput中沒有用到的getName方法借用一下,把editorID放到此方法里面,這樣就可以用下面的方式來得到IEditorInput和editorID了.
String key = ""+list.getSelectionIndex();
IEditorInput editorInput = (IEditorInput)list.getData(key);
String editorID = editorInput.getnName();
在實際開發綜合很多界面都是創建在編輯器上,雖然在這里是只講了最常用的編輯器使用方法,但已經足夠應付大部分開發的需要,如果你想了解更多關於編輯器的信息,可以查閱編輯器的幫助文檔,它在幫助中的位置是"平台插件開發者指南--->程序員指南----->編輯器".
將在透視圖中添加上對應的編輯器類:(這種效果就像在Eclipse張雙擊Java源文件,打開文件的編輯器一樣)
和以前一樣,先來修改plugin.xml文件將編輯器的擴展點加入,然后再創建相應的編輯器類.最后編寫列表的事件代碼.
plugin.xml
<?xml version="1.0" encoding="UTF-8"?> <?eclipse version="3.4"?> <plugin> <extension point="org.eclipse.ui.perspectives"> <perspective name="myplugin 透視圖" icon="icons/selectall.gif" class="cn.com.kxh.myplugin.SamplePerspective" id="cn.com.kxh.myplugin.SamplePerspective"> </perspective> </extension> <extension point="org.eclipse.ui.views"> <view name="視圖1" icon="icons/prev.gif" category="com.glkxh.myplugin.view" class="cn.com.kxh.myplugin.View1" id="cn.com.kxh.myplugin.View1"> </view> <view name="視圖2" icon="icons/project.gif" category="com.glkxh.myplugin.view" class="cn.com.kxh.myplugin.View2" id="cn.com.kxh.myplugin.View2"> </view> </extension> <extension point="org.eclipse.ui.editors"> <editor name="中國Editor" icon="icons/project.gif" class="cn.com.kxh.myplugin.ChinaEditor" id="cn.com.kxh.myplugin.ChinaEditor"> </editor> <editor name="美國Editor" icon="icons/prev.gif" class="cn.com.kxh.myplugin.UsaEditor" id="cn.com.kxh.myplugin.UsaEditor"> </editor> <editor name="法國Editor" icon="icons/remove.gif" class="cn.com.kxh.myplugin.FranceEditor" id="cn.com.kxh.myplugin.FranceEditor"> </editor> </extension> </plugin>
上述代碼說明:編輯器的擴展點是org.eclipse.ui.editors,它各項的含義和視圖擴展點基本一樣,可參照視圖擴展點的說明,這里強調一點:icon是必填項.
編輯器必須實現IEditorPart接口,但通常是繼承抽象類EditorPart類(EditorPart是IEditorPart的子類).繼承EditorPart的子類必須實現父類的7個方法,在此先實現方法init,createPartControl,其他方法空實現.
代碼說明:編輯器的擴展點是org.eclispse.ui.editor
ChinaEditor.java
1 public class ChinaEditor extends EditorPart { 2 private boolean dirty = true; // 編輯器是否為臟的標識 3 4 // Editor的初始化方法。本方法前兩句是固定不變的 5 public void init(IEditorSite site, IEditorInput input) throws PartInitException { 6 System.out.println("init"); 7 setSite(site); 8 setInput(input); 9 // 下一句設置Editor標題欄的顯示名稱,否則名稱用plugin.xml中的name屬性 10 // setPartName(input.getName()); 11 // 下一句設置Editor標題欄的圖標,否則會自動使用一個默認的圖標 12 // setTitleImage(input.getImageDescriptor().createImage()); 13 } 14 15 // 在此方法中創建Editor中的界面組件 16 public void createPartControl(Composite parent) { 17 System.out.println("createPartControl"); 18 Composite topComp = new Composite(parent, SWT.NONE); 19 topComp.setLayout(new FillLayout()); 20 Text text = new Text(topComp, SWT.BORDER); 21 text.setText("中國之編輯器"); 22 23 text.addKeyListener(new KeyAdapter() { 24 public void keyPressed(KeyEvent e) { 25 // 如果編輯器不臟(即沒有修改),則標志它臟並刷新界面狀態 26 if (!isDirty()) { 27 setDirty(true); 28 firePropertyChange(IEditorPart.PROP_DIRTY); 29 } 30 } 31 }); 32 } 33 34 // 保存的處理代碼在這種方法中,當按Ctrl+S鍵時會執行此方法。 35 // 最后別忘記標志為非臟及刷新界面狀態 36 public void doSave(IProgressMonitor monitor) { 37 if (isDirty()) { 38 // ……保存編輯器事件處理代碼(省略) 39 setDirty(false); 40 firePropertyChange(IEditorPart.PROP_DIRTY); 41 } 42 } 43 44 // 是否允許“另存為”,false不允許 45 public boolean isSaveAsAllowed() { 46 return false; 47 } 48 49 // “另存為”的代碼寫在這里,本例不實現它 50 public void doSaveAs() {} 51 52 // dirty標識的set方法,由此方法設置編輯器為臟 53 public void setDirty(boolean dirty) { 54 this.dirty = dirty; 55 } 56 57 // 編輯器的內容是否臟了。true臟,false不臟 58 public boolean isDirty() { 59 return dirty; 60 } 61 62 // 當編輯器獲得焦點時會執行此方法,本例空實現 63 public void setFocus() {} 64 }
獲取視圖對象是用IWorkbenchPage的findView方法,方法參數是視圖在plugin.xml中的id標識,獲取編輯器對象是用findEditor方法,但該方法的參數卻不是id標識,而是一個IEditorInput對象.另外,加載一個編輯器是用IWorkbenchPage的openEditor(editorInput,editorID)方法.
由上可知,一個編輯器要對應一個IEditorInput和EditorPart,而且在IWorkbenchPage中是根據IEditorInput來取得EditorPart.
附上關系圖:
ChinaEditorInput.java
1 public class ChinaEditorInput implements IEditorInput { 2 3 // 返回true,則打開該編輯器后它會出現在Eclipse主菜單“文件” 4 // 最下部的最近打開的文檔欄中。返回flase則不出現在其中。 5 @Override 6 public boolean exists() { 7 return true; 8 } 9 10 // 編輯器標題欄的圖標,不過它還需要在ChinaEditor中用 11 // setTitleImage方法設置,才能出現在標題欄中。 12 @Override 13 public ImageDescriptor getImageDescriptor() { 14 // return WorkbenchImages.getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_HOME_NAV); 15 return null; 16 } 17 18 // 編輯器標題欄的顯示名稱,和上面的getImageDescriptor一樣也要 19 // 在ChinaEditor中用setPartName方法設置,才能出現在標題欄中。 20 @Override 21 public String getName() { 22 return "中國的編輯器"; 23 } 24 25 // 編輯器標題欄的小黃條提示文字,不需象getName那樣在ChinaEditor中再設置 26 @Override 27 public String getToolTipText() { 28 return "這是視圖1列表中的中國項對應的編輯器"; 29 } 30 31 // 返回一個可以用做保存本編輯輸入數據狀態的對象 32 @Override 33 public IPersistableElement getPersistable() { 34 return null; 35 } 36 37 // 得到一個編輯器的適配器 38 // IAdaptable a = new ChinaEditorInput(); 39 // IFoo x = (IFoo)a.getAdapter(IFoo.class); 40 // if (x != null) [用x來做IFoo的事情....] 41 @Override 42 public Object getAdapter(Class adapter) { 43 return null; 44 } 45 }
FranceEditor.java
1 public class FranceEditor extends EditorPart { 2 3 public void doSave(IProgressMonitor monitor) {} 4 5 public void doSaveAs() {} 6 7 public void init(IEditorSite site, IEditorInput input) throws PartInitException { 8 setSite(site); 9 setInput(input); 10 } 11 12 public boolean isDirty() { 13 return false; 14 } 15 16 public boolean isSaveAsAllowed() { 17 return false; 18 } 19 20 public void createPartControl(Composite parent) { 21 Composite topComp = new Composite(parent, SWT.NONE); 22 topComp.setLayout(new FillLayout()); 23 Text text = new Text(topComp, SWT.BORDER); 24 text.setText("法國之編輯器"); 25 } 26 27 public void setFocus() {} 28 29 }
FranceEditorInput.java
1 public class FranceEditorInput implements IEditorInput { 2 3 public boolean exists() { 4 return false; 5 } 6 7 public ImageDescriptor getImageDescriptor() { 8 return null; 9 } 10 11 public String getName() { 12 return "法國的編輯器"; 13 } 14 15 public IPersistableElement getPersistable() { 16 return null; 17 } 18 19 public String getToolTipText() { 20 return "這是視圖1列表中的法國項對應的編輯器"; 21 } 22 23 public Object getAdapter(Class adapter) { 24 return null; 25 } 26 27 }
UsaEditor.java
public class UsaEditor extends EditorPart { public void doSave(IProgressMonitor monitor) {} public void doSaveAs() {} public void init(IEditorSite site, IEditorInput input) throws PartInitException { setSite(site); setInput(input); } public boolean isDirty() { return false; } public boolean isSaveAsAllowed() { return false; } public void createPartControl(Composite parent) { Composite topComp = new Composite(parent, SWT.NONE); topComp.setLayout(new FillLayout()); Text text = new Text(topComp, SWT.BORDER); text.setText("美國之編輯器"); } public void setFocus() {} }
UsaEditorInput.java
1 public class UsaEditorInput implements IEditorInput { 2 3 public boolean exists() { 4 return false; 5 } 6 7 public ImageDescriptor getImageDescriptor() { 8 return null; 9 } 10 11 public String getName() { 12 return "美國的編輯器"; 13 } 14 15 public IPersistableElement getPersistable() { 16 return null; 17 } 18 19 public String getToolTipText() { 20 return "這是視圖1列表中的美國項對應的編輯器"; 21 } 22 23 public Object getAdapter(Class adapter) { 24 return null; 25 } 26 27 }