本例将给视图加入下拉菜单和按钮,同时再为列表添加一个右键菜单.
创建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 }