Eclipse RCP开发桌面程序

时间:2023-01-20 21:53:32
转自:http://www.cnblogs.com/kentyshang/archive/2007/08/02/840027.aspx

所 谓RCP,就是Rich Client Platform的缩写,即富客户平台,是Eclipse进化的产物(自3.0版以后出现),是Eclipse组织向用户提供的强大的开放性开发平台,能 够使用户方便地创建自己的基于Eclipse的应用程序,并且这些应用程序能够得到Eclipse的底层支持。更重要的是,我们可以利用Java创建象 Eclipse这么漂亮的桌面程序。

  我相信,在未来的几年里,RCP一定会变得非常流行。使用RCP,我们可以开发界面象 Eclipse这样漂亮的桌面程序,比如医院管理系统啊、CAD软件等等。遗憾的是,目前在国内基本上找不到关于RCP的中文资料,我们只能通过自己的探 索来为我们的程序添加我们想要的功能。

  下面让我们一步一步来建立一个Eclipse RCP程序,下面的内容可以说在Google上一搜一大把,有些人会觉得乏味,但是没关系,这只是一个快速的起步。

  选择“新建--项目”,选择“插件项目”:
Eclipse RCP开发桌面程序

Eclipse RCP开发桌面程序

点下一步,输入项目名称,选择Eclipse版本,我这里选择的是3.2:
Eclipse RCP开发桌面程序

  点下一步,插件标识和插件名称可以更改,其他的内容都可以保持默认,一定要记得选中富客户机应用程序支持:
Eclipse RCP开发桌面程序

  点下一步,选中一个模板,这里选一个最简单的,到时候看源代码的时候便于理解:
Eclipse RCP开发桌面程序

  点下一步,改一下应用程序标题:
Eclipse RCP开发桌面程序

  点完成,我们可以在项目上面点右键,选择按Eclipse程序运行,就可以看到效果了:
Eclipse RCP开发桌面程序

Eclipse RCP开发桌面程序

  在这个程序中,窗口上显示的是一个透视图,透视图中含有一个编辑器区域,以后,我们可以逐步为这个程序添加菜单、工具条和为这个透视图添加视图、编辑器等等。

  现在,这个程序只能在Eclipse环境下运行,而RCP的目标是创建可以独立运行的应用程序,我们的事情还没完呢。下一步,在项目上点右键,创建产品配置文件:
Eclipse RCP开发桌面程序

  输入产品配置文件名:

Eclipse RCP开发桌面程序

  生成的产品配置文件在编辑器中打开,应该是这个样子的:
Eclipse RCP开发桌面程序

  刚开始,上面的几个文本框都是空的,点新建按钮之后,弹出如下的对话框,输入产品名称后,点完成就行了。

Eclipse RCP开发桌面程序

  点击配置文件中的“启动程序”,我们可以试着启动我们的RCP程序。结果呢,会出错。原因很简单,因为我们没有为我们的程序选中它依赖的插件。

   选中配置文件的“配置”选项卡,添加以下几个依赖项,记住,一定要把我们自己,也就是com.blogjava.youxia.rcp_start加进依赖项,否则会出错。最开始的时候,就是这么一点小问题,让我浪费了几天时间。
Eclipse RCP开发桌面程序

  再点击添加必须的插件,自动添加其它的依赖项。

  再下一步,设置项目的构建路径,如下图:
Eclipse RCP开发桌面程序

  下一步,导出我们的程序:
Eclipse RCP开发桌面程序

Eclipse RCP开发桌面程序

  点下一步,输入我们程序导出的目录,如下图:
Eclipse RCP开发桌面程序

  点完成按钮之后,我们的程序就导出到我们的指定的目录中了,打开这个目录,可以看到一个类似eclipse的程序图标,双击运行,效果如下图:Eclipse RCP开发桌面程序

  最后,需要说明两点:第一,如果希望生成的程序有自己的图标,可以在产品配置文件中的最后两个配置文件中设置;第二,生成的程序应该是没有菜单栏的,因为我的Eclipse安装了MyEclipse,所以导出的程序就多了两个菜单。

  好了,快速起步就到这里了,以后再仔细研究生成的代码和为我们的程序添加功能。
=========================================================================
使用Eclipse RCP进行桌面程序开发(一):快速起步中,我们通过Eclipse的插件开发向导,逐步建立了一个RCP应用程序,但是,这个程序没有任何功能,难以激起我们学习的兴趣。在这一节,我们将一起探索怎样在程序中添加菜单和工具条。先看一下成果:

图一、图二:带有菜单和工具条的RCP程序
Eclipse RCP开发桌面程序

Eclipse RCP开发桌面程序

图三:工具栏上的按钮的提示文本
Eclipse RCP开发桌面程序

图四:点击菜单项或者工具栏按钮后,弹出一个简单的对话框。
Eclipse RCP开发桌面程序

这 里需要说明一点,为什么要在讲菜单和工具栏的时候一起讲对话框,这是因为对话框是我们所能想到的最简单最直接的用户交互方式,在对话框上可以添加各种各样 的控件来实现复杂的功能,为了让我们点击菜单项的时候能够看到效果,这里就用了一个简单的对话框。当然,当我们以后接触到视图、编辑器和透视图这样的概念 之后,我们能使用的用户交互方式就不仅仅只是对话框了。

打开我们上一节使用向导建立的工程,可以发现工程下面自动生成了如下文件:
Application.java
ApplicationWorkbenchAdvisor.java
ApplicationWorkbenchWindowAdvisor.java
ApplicationActionBarAdvisor.java
Perspective.java
plugin.xml
这里的Application.java是我们整个程序的入口点,我们的程序运行的时候,会先执行Application的run方法,run方法的代码如下:

 1 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序public  Object run(Object args)  throws  Exception  {
 2 Eclipse RCP开发桌面程序        Display display  =  PlatformUI.createDisplay();
 3 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序         try   {
 4 Eclipse RCP开发桌面程序             int  returnCode  =  PlatformUI.createAndRunWorkbench(display,  new  ApplicationWorkbenchAdvisor());
 5 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序             if  (returnCode  ==  PlatformUI.RETURN_RESTART)  {
 6 Eclipse RCP开发桌面程序                 return  IPlatformRunnable.EXIT_RESTART;
 7 Eclipse RCP开发桌面程序            }

 8 Eclipse RCP开发桌面程序             return  IPlatformRunnable.EXIT_OK;
 9 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        }
  finally   {
10 Eclipse RCP开发桌面程序            display.dispose();
11 Eclipse RCP开发桌面程序        }

12 Eclipse RCP开发桌面程序    }

在第4行我们可以看出,该入口函数将创建用户界面的工作交给了ApplicationWorkbenchAdvisor类。接着,我们打开ApplicationWorkbenchAdvisor.java,代码如下:

 1 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序public   class  ApplicationWorkbenchAdvisor  extends  WorkbenchAdvisor  {
 2 Eclipse RCP开发桌面程序
 3 Eclipse RCP开发桌面程序     private   static   final  String PERSPECTIVE_ID  =   " cn.blogjava.youxia.rcp_start.perspective " ;
 4 Eclipse RCP开发桌面程序
 5 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public  WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer)  {
 6 Eclipse RCP开发桌面程序         return   new  ApplicationWorkbenchWindowAdvisor(configurer);
 7 Eclipse RCP开发桌面程序    }

 8 Eclipse RCP开发桌面程序
 9 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public  String getInitialWindowPerspectiveId()  {
10 Eclipse RCP开发桌面程序         return  PERSPECTIVE_ID;
11 Eclipse RCP开发桌面程序    }

12 Eclipse RCP开发桌面程序}

可 以看出,这个类的工作就是为我们的程序指定默认的透视图,然后把创建窗口的工作交给了 ApplicationWorkbenchWindowAdvisor类。接着,我们打开 ApplicationWorkbenchWindowAdvisor.java文件,看到代码如下:

 1 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序public   class  ApplicationWorkbenchWindowAdvisor  extends  WorkbenchWindowAdvisor  {
 2 Eclipse RCP开发桌面程序
 3 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public  ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer)  {
 4 Eclipse RCP开发桌面程序         super (configurer);
 5 Eclipse RCP开发桌面程序    }

 6 Eclipse RCP开发桌面程序
 7 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public  ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer)  {
 8 Eclipse RCP开发桌面程序         return   new  ApplicationActionBarAdvisor(configurer);
 9 Eclipse RCP开发桌面程序    }

10 Eclipse RCP开发桌面程序    
11 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public   void  preWindowOpen()  {
12 Eclipse RCP开发桌面程序        IWorkbenchWindowConfigurer configurer  =  getWindowConfigurer();
13 Eclipse RCP开发桌面程序        configurer.setInitialSize( new  Point( 600 450 ));
14 Eclipse RCP开发桌面程序        configurer.setShowCoolBar( true );
15 Eclipse RCP开发桌面程序        configurer.setShowStatusLine( false );
16 Eclipse RCP开发桌面程序        configurer.setTitle( " 第一个RCP程序 " );
17 Eclipse RCP开发桌面程序        
18 Eclipse RCP开发桌面程序    }

19 Eclipse RCP开发桌面程序       
20 Eclipse RCP开发桌面程序}

这 个类的功能很强大,我们可以重载它的preWindowCreate、postWindowCreate、preWindowOpen、 postWindowOpen等方法,以便修改我们窗口的外观。在这里可以看出,我们重载了preWindowOpen方法来设置窗口的大小和让工具栏可 见。很显然,这个类的另外一个功能,就是把创建菜单和工具栏的任务交给了ApplicationActionBarAdvisor类。

到这里,谜底已经揭晓,要创建我们自己的菜单和工具条,就一定是在ApplicationActionBarAdvisor.java中做文章了。不错,打开这个文件,我们可以看到这个类有两个重要的方法:
protected void makeActions(IWorkbenchWindow window);
protected void fillMenuBar(IMenuManager menuBar);
我 们可以在makeActions方法中创建我们的Action,什么是Action呢?Action是jface中的一个概念,在jface中通过 org.eclipse.jface.action中的Action和ActionContributionItem类实现了视图和处理代码的分离,这样 无论何时用户触发了一个控件的事件,都会激活一个相应的Action类实例来进行时间处理。毫无疑问,我们的菜单项是一个Action类的子类了。

下面请看ApplicationActionBarAdvisor.java的源代码:

 1 Eclipse RCP开发桌面程序package  cn.blogjava.youxia.rcp_start;
 2 Eclipse RCP开发桌面程序
 3 Eclipse RCP开发桌面程序 import  org.eclipse.jface.action.IMenuManager;
 4 Eclipse RCP开发桌面程序 import  org.eclipse.jface.action.MenuManager;
 5 Eclipse RCP开发桌面程序 import  org.eclipse.ui.IWorkbenchWindow;
 6 Eclipse RCP开发桌面程序 import  org.eclipse.ui.application.ActionBarAdvisor;
 7 Eclipse RCP开发桌面程序 import  org.eclipse.ui.application.IActionBarConfigurer;
 8 Eclipse RCP开发桌面程序 import  org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
 9 Eclipse RCP开发桌面程序 import  cn.blogjava.youxia.actions.Action1;
10 Eclipse RCP开发桌面程序
11 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序 public   class  ApplicationActionBarAdvisor  extends  ActionBarAdvisor  {
12 Eclipse RCP开发桌面程序    
13 Eclipse RCP开发桌面程序     private  IWorkbenchAction action1;
14 Eclipse RCP开发桌面程序
15 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public  ApplicationActionBarAdvisor(IActionBarConfigurer configurer)  {
16 Eclipse RCP开发桌面程序         super (configurer);
17 Eclipse RCP开发桌面程序    }

18 Eclipse RCP开发桌面程序
19 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     protected   void  makeActions(IWorkbenchWindow window)  {
20 Eclipse RCP开发桌面程序        action1  =   new  Action1(window);
21 Eclipse RCP开发桌面程序        action1.setText( " 第一个菜单项 " );
22 Eclipse RCP开发桌面程序        action1.setId( " cn.blogjava.youxia.actions.action1 " );
23 Eclipse RCP开发桌面程序        register(action1);
24 Eclipse RCP开发桌面程序    }

25 Eclipse RCP开发桌面程序
26 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     protected   void  fillMenuBar(IMenuManager menuBar)  {
27 Eclipse RCP开发桌面程序        MenuManager newMenu  =   new  MenuManager( " 第一个菜单 " , " cn.blogjava.youxia.firstmenu " );
28 Eclipse RCP开发桌面程序        menuBar.add(newMenu);
29 Eclipse RCP开发桌面程序        newMenu.add(action1);
30 Eclipse RCP开发桌面程序    }

31 Eclipse RCP开发桌面程序   
32 Eclipse RCP开发桌面程序}

可 以看出,我们通过创建cn.blogjava.youxia.actions.Action1类的实例来创建一个菜单项,然后把它加入到菜单 newMenu中,然后再把newMenu加入menuBar中,整个过程很容易理解。那么register(action1)是做什么的呢?这是为了把 我们的Action的实例注册到工作台中,这样当我们的工作台销毁的时候,我们的Action也可以被销毁。

下面请看Action1类的源代码:

 1 Eclipse RCP开发桌面程序package  cn.blogjava.youxia.actions;
 2 Eclipse RCP开发桌面程序
 3 Eclipse RCP开发桌面程序 import  org.eclipse.jface.action.Action;
 4 Eclipse RCP开发桌面程序 import  org.eclipse.ui.IWorkbenchWindow;
 5 Eclipse RCP开发桌面程序 import  org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
 6 Eclipse RCP开发桌面程序 import  cn.blogjava.youxia.rcp_start.FirstDialog;
 7 Eclipse RCP开发桌面程序
 8 Eclipse RCP开发桌面程序
 9 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序 public   class  Action1  extends  Action  implements  IWorkbenchAction  {
10 Eclipse RCP开发桌面程序    
11 Eclipse RCP开发桌面程序     private  IWorkbenchWindow workbenchWindow;
12 Eclipse RCP开发桌面程序
13 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public  Action1(IWorkbenchWindow window)  {
14 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序         if  (window  ==   null {
15 Eclipse RCP开发桌面程序             throw   new  IllegalArgumentException();
16 Eclipse RCP开发桌面程序        }

17 Eclipse RCP开发桌面程序
18 Eclipse RCP开发桌面程序         this .workbenchWindow  =  window;
19 Eclipse RCP开发桌面程序    }

20 Eclipse RCP开发桌面程序    
21 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public   void  run()  {
22 Eclipse RCP开发桌面程序         //  make sure action is not disposed
23 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序         if  (workbenchWindow  !=   null {
24 Eclipse RCP开发桌面程序             // 在这里添加功能
25 Eclipse RCP开发桌面程序            FirstDialog dg  =   new  FirstDialog(workbenchWindow.getShell());
26 Eclipse RCP开发桌面程序            dg.open();
27 Eclipse RCP开发桌面程序            
28 Eclipse RCP开发桌面程序        }

29 Eclipse RCP开发桌面程序    }

30 Eclipse RCP开发桌面程序
31 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public   void  dispose()  {
32 Eclipse RCP开发桌面程序        workbenchWindow  =   null ;
33 Eclipse RCP开发桌面程序
34 Eclipse RCP开发桌面程序    }

35 Eclipse RCP开发桌面程序
36 Eclipse RCP开发桌面程序}

在 构造函数中保存我们工作台窗口的引用,在run方法中执行功能,是不是很简单?在这里,我们用到了一个对话框类 cn.blogjava.youxia.rcp_start.FirstDialog,这个类从 org.eclipse.swt.widgets.Dialog类继承,熟悉swt的朋友一定不会陌生。我建议大家可以使用Designer插件,这个插 件对swt/jface提供非常好的可视化支持,在这个对话框中,我们只简单的添加了两个按钮。

FirstDialog.java源文件如下:

 1 Eclipse RCP开发桌面程序package  cn.blogjava.youxia.rcp_start;
 2 Eclipse RCP开发桌面程序
 3 Eclipse RCP开发桌面程序 import  org.eclipse.swt.SWT;
 4 Eclipse RCP开发桌面程序 import  org.eclipse.swt.events.SelectionAdapter;
 5 Eclipse RCP开发桌面程序 import  org.eclipse.swt.events.SelectionEvent;
 6 Eclipse RCP开发桌面程序 import  org.eclipse.swt.widgets.Button;
 7 Eclipse RCP开发桌面程序 import  org.eclipse.swt.widgets.Dialog;
 8 Eclipse RCP开发桌面程序 import  org.eclipse.swt.widgets.Display;
 9 Eclipse RCP开发桌面程序 import  org.eclipse.swt.widgets.Shell;
10 Eclipse RCP开发桌面程序
11 Eclipse RCP开发桌面程序
12 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序 public   class  FirstDialog  extends  Dialog  {
13 Eclipse RCP开发桌面程序
14 Eclipse RCP开发桌面程序     protected  Shell shell;
15 Eclipse RCP开发桌面程序    
16 Eclipse RCP开发桌面程序     private   int  result;
17 Eclipse RCP开发桌面程序
18 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public  FirstDialog(Shell parent,  int  style)  {
19 Eclipse RCP开发桌面程序         super (parent, style);
20 Eclipse RCP开发桌面程序    }

21 Eclipse RCP开发桌面程序
22 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public  FirstDialog(Shell parent)  {
23 Eclipse RCP开发桌面程序         this (parent, SWT.NONE);
24 Eclipse RCP开发桌面程序    }

25 Eclipse RCP开发桌面程序
26 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public   int  open()  {
27 Eclipse RCP开发桌面程序        createContents();
28 Eclipse RCP开发桌面程序        shell.open();
29 Eclipse RCP开发桌面程序        shell.layout();
30 Eclipse RCP开发桌面程序        Display display  =  getParent().getDisplay();
31 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序         while  ( ! shell.isDisposed())  {
32 Eclipse RCP开发桌面程序             if  ( ! display.readAndDispatch())
33 Eclipse RCP开发桌面程序                display.sleep();
34 Eclipse RCP开发桌面程序        }

35 Eclipse RCP开发桌面程序         return  result;
36 Eclipse RCP开发桌面程序    }

37 Eclipse RCP开发桌面程序
38 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     protected   void  createContents()  {
39 Eclipse RCP开发桌面程序        shell  =   new  Shell(getParent(), SWT.DIALOG_TRIM  |  SWT.APPLICATION_MODAL);
40 Eclipse RCP开发桌面程序        shell.setSize( 150 70 );
41 Eclipse RCP开发桌面程序        shell.setText( " 第一个对话框 " );
42 Eclipse RCP开发桌面程序
43 Eclipse RCP开发桌面程序         final  Button okButton  =   new  Button(shell, SWT.NONE);
44 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        okButton.addSelectionListener( new  SelectionAdapter()  {
45 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序             public   void  widgetSelected(SelectionEvent e)  {
46 Eclipse RCP开发桌面程序                result  =   1 ;
47 Eclipse RCP开发桌面程序                shell.dispose();
48 Eclipse RCP开发桌面程序            }

49 Eclipse RCP开发桌面程序        }
);
50 Eclipse RCP开发桌面程序        okButton.setText( " OK " );
51 Eclipse RCP开发桌面程序        okButton.setBounds( 10 10 48 22 );
52 Eclipse RCP开发桌面程序
53 Eclipse RCP开发桌面程序         final  Button cancelButton  =   new  Button(shell, SWT.NONE);
54 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        cancelButton.addSelectionListener( new  SelectionAdapter()  {
55 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序             public   void  widgetSelected(SelectionEvent e)  {
56 Eclipse RCP开发桌面程序                result  =   2 ;
57 Eclipse RCP开发桌面程序                shell.dispose();
58 Eclipse RCP开发桌面程序            }

59 Eclipse RCP开发桌面程序        }
);
60 Eclipse RCP开发桌面程序        cancelButton.setText( " Cancel " );
61 Eclipse RCP开发桌面程序        cancelButton.setBounds( 89 10 48 22 );
62 Eclipse RCP开发桌面程序    }

63 Eclipse RCP开发桌面程序
64 Eclipse RCP开发桌面程序}

65 Eclipse RCP开发桌面程序


上面所讲的,只是添加菜单和工具栏的第一种方法,这种方法把构建菜单的工作以静态代码的方式加入到了ApplicationActionBarAdvisor类中,如果需要修改用户界面,则需要修改代码并重新编译。

添加菜单项的第二种方法就要简单得多,而且修改起来也方便,还可以对菜单项实现更加灵活的控制,但是,需要对Eclipse的插件基础有比较好的了解。那这第二种方法就是通过扩展actionSets扩展点来添加菜单。

对扩展点的扩展,可以通过编辑plugin.xml文件了实现,比如我们添加的第二个菜单项,其配置文件如下:

 

 1 Eclipse RCP开发桌面程序< extension
 2 Eclipse RCP开发桌面程序          id ="cn.blogjava.youxia.actionset"
 3 Eclipse RCP开发桌面程序         name ="我的菜单扩展"
 4 Eclipse RCP开发桌面程序         point ="org.eclipse.ui.actionSets" >
 5 Eclipse RCP开发桌面程序       < actionSet
 6 Eclipse RCP开发桌面程序             description ="第一个扩展"
 7 Eclipse RCP开发桌面程序            id ="RCP_Start.actionSet1"
 8 Eclipse RCP开发桌面程序            label ="RCP_Start.actionSet1"
 9 Eclipse RCP开发桌面程序            visible ="true" >
10 Eclipse RCP开发桌面程序          < action
11 Eclipse RCP开发桌面程序                class ="cn.blogjava.youxia.actions.Action2"
12 Eclipse RCP开发桌面程序               icon ="icons/alt_window_16.gif"
13 Eclipse RCP开发桌面程序               id ="RCP_Start.action2"
14 Eclipse RCP开发桌面程序               label ="第二个菜单项"
15 Eclipse RCP开发桌面程序               menubarPath ="cn.blogjava.youxia.firstmenu/additions"
16 Eclipse RCP开发桌面程序               style ="push"
17 Eclipse RCP开发桌面程序               toolbarPath ="additions"
18 Eclipse RCP开发桌面程序               tooltip ="第二个菜单项的按钮" />
19 Eclipse RCP开发桌面程序       </ actionSet >
20 Eclipse RCP开发桌面程序    </ extension >

其实Eclipse为我们提供了很好的可视化plugin.xml的编辑器,如下图,我们可以对菜单的外观进行和行为进行灵活的控制:

Eclipse RCP开发桌面程序

从 配置文件中我们可以看到,我们为这第二个菜单项指定的Action是cn.blogjava.youxia.actions.Action2类,这个类我 们必须实现org.eclipse.ui.IWorkbenchWindowActionDelegate接口,这个接口中比 org.eclipse.jface.actions.Action中多定义了一个方法public void selectionChanged(IAction action, ISelection selection),这个方法是必须的,以便工作台窗口在用户选定哪一项资源的时候通知我们的Action类的实例。其代码如下:

 1 Eclipse RCP开发桌面程序package  cn.blogjava.youxia.actions;
 2 Eclipse RCP开发桌面程序
 3 Eclipse RCP开发桌面程序 import  org.eclipse.jface.action.IAction;
 4 Eclipse RCP开发桌面程序 import  org.eclipse.jface.viewers.ISelection;
 5 Eclipse RCP开发桌面程序 import  org.eclipse.ui.IWorkbenchWindow;
 6 Eclipse RCP开发桌面程序 import  org.eclipse.ui.IWorkbenchWindowActionDelegate;
 7 Eclipse RCP开发桌面程序 import  cn.blogjava.youxia.rcp_start.FirstDialog;
 8 Eclipse RCP开发桌面程序
 9 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序 public   class  Action2  implements  IWorkbenchWindowActionDelegate  {
10 Eclipse RCP开发桌面程序    
11 Eclipse RCP开发桌面程序     private  IWorkbenchWindow window;
12 Eclipse RCP开发桌面程序
13 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public   void  dispose()  {
14 Eclipse RCP开发桌面程序         //  TODO 
15 Eclipse RCP开发桌面程序
16 Eclipse RCP开发桌面程序    }

17 Eclipse RCP开发桌面程序
18 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public   void  init(IWorkbenchWindow window)  {
19 Eclipse RCP开发桌面程序         //  TODO 
20 Eclipse RCP开发桌面程序         this .window  =  window;
21 Eclipse RCP开发桌面程序
22 Eclipse RCP开发桌面程序    }

23 Eclipse RCP开发桌面程序
24 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public   void  run(IAction action)  {
25 Eclipse RCP开发桌面程序         //  TODO 
26 Eclipse RCP开发桌面程序        FirstDialog dg  =   new  FirstDialog(window.getShell());
27 Eclipse RCP开发桌面程序        dg.open();
28 Eclipse RCP开发桌面程序
29 Eclipse RCP开发桌面程序    }

30 Eclipse RCP开发桌面程序
31 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public   void  selectionChanged(IAction action, ISelection selection)  {
32 Eclipse RCP开发桌面程序         //  TODO 
33 Eclipse RCP开发桌面程序
34 Eclipse RCP开发桌面程序    }

35 Eclipse RCP开发桌面程序
36 Eclipse RCP开发桌面程序}


总结:通过向工作台中添加菜单和工具栏,并使用对话框作为与用户交互的基础,我们已经基本上可以构建功能比较复杂的程序了。但这仅仅只是RCP编程的开端。下一节,我们将一起探索Eclipse的透视图和视图。
===============================================================
Eclipse RCP开发中,和用户进行交互最多的界面,应该是视图了,而透视图就是将已有的视图、菜单、工具栏、编辑器等等进行组合和布局。看完这一节,我们就可以建立如下图这样的程序界面了。

Eclipse RCP开发桌面程序

首 先我们来介绍一下视图,建立一个视图其实非常简单,只要从org.eclipse.ui.part.ViewPart继承一个类,然后在 plugin.xml中进行视图的配置。其中,向视图中添加控件的操作,我们即可以手工编写,也可以使用Designer插件,我这里推荐大家使用 Designer插件,该插件对RCP提供功能非常强大的支持,如果使用Designer插件开发视图,则plugin.xml文件也不需要我们手动修改 了。

比如我们上图中的第一个视图,就是从ViewPart继承一个类,然后在上面加入了几个swt的控件,做得非常得简单,而它的配置文件如下:

1 Eclipse RCP开发桌面程序< extension
2 Eclipse RCP开发桌面程序          point ="org.eclipse.ui.views" >
3 Eclipse RCP开发桌面程序       < view
4 Eclipse RCP开发桌面程序             class ="cn.blogjava.youxia.views.FirstView"
5 Eclipse RCP开发桌面程序            id ="cn.blogjava.youxia.views.FirstView"
6 Eclipse RCP开发桌面程序            name ="第一个View" />
7 Eclipse RCP开发桌面程序 </ extension >


可以看到,实现这个视图的class为cn.blogjava.youxia.views.FirstView,那么我们看看FirstView.java吧:

 1 Eclipse RCP开发桌面程序package  cn.blogjava.youxia.views;
 2 Eclipse RCP开发桌面程序
 3 Eclipse RCP开发桌面程序 import  org.eclipse.jface.action.IMenuManager;
 4 Eclipse RCP开发桌面程序 import  org.eclipse.jface.action.IToolBarManager;
 5 Eclipse RCP开发桌面程序 import  org.eclipse.jface.viewers.TableViewer;
 6 Eclipse RCP开发桌面程序 import  org.eclipse.swt.SWT;
 7 Eclipse RCP开发桌面程序 import  org.eclipse.swt.widgets.Composite;
 8 Eclipse RCP开发桌面程序 import  org.eclipse.swt.widgets.Label;
 9 Eclipse RCP开发桌面程序 import  org.eclipse.swt.widgets.Table;
10 Eclipse RCP开发桌面程序 import  org.eclipse.swt.widgets.Text;
11 Eclipse RCP开发桌面程序 import  org.eclipse.ui.part.ViewPart;
12 Eclipse RCP开发桌面程序
13 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序 public   class  FirstView  extends  ViewPart  {
14Eclipse RCP开发桌面程序
15Eclipse RCP开发桌面程序    private Table table;
16Eclipse RCP开发桌面程序    private Text text_1;
17Eclipse RCP开发桌面程序    private Text text;
18Eclipse RCP开发桌面程序    public static final String ID = "cn.blogjava.youxia.views.FirstView"//$NON-NLS-1$
19Eclipse RCP开发桌面程序
20Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    /**
21Eclipse RCP开发桌面程序     * Create contents of the view part
22Eclipse RCP开发桌面程序     * @param parent
23Eclipse RCP开发桌面程序     */

24Eclipse RCP开发桌面程序    @Override
25Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void createPartControl(Composite parent) {
26Eclipse RCP开发桌面程序        Composite container = new Composite(parent, SWT.NONE);
27Eclipse RCP开发桌面程序
28Eclipse RCP开发桌面程序        final Label label = new Label(container, SWT.NONE);
29Eclipse RCP开发桌面程序        label.setText("姓名:");
30Eclipse RCP开发桌面程序        label.setBounds(56413612);
31Eclipse RCP开发桌面程序
32Eclipse RCP开发桌面程序        text = new Text(container, SWT.BORDER);
33Eclipse RCP开发桌面程序        text.setBounds(98388015);
34Eclipse RCP开发桌面程序
35Eclipse RCP开发桌面程序        final Label label_1 = new Label(container, SWT.NONE);
36Eclipse RCP开发桌面程序        label_1.setText("性别:");
37Eclipse RCP开发桌面程序        label_1.setBounds(212413012);
38Eclipse RCP开发桌面程序
39Eclipse RCP开发桌面程序        text_1 = new Text(container, SWT.BORDER);
40Eclipse RCP开发桌面程序        text_1.setBounds(252388015);
41Eclipse RCP开发桌面程序
42Eclipse RCP开发桌面程序        final TableViewer tableViewer = new TableViewer(container, SWT.BORDER);
43Eclipse RCP开发桌面程序        //tableViewer.setInput(new Object());
44Eclipse RCP开发桌面程序        table = tableViewer.getTable();
45Eclipse RCP开发桌面程序        table.setBounds(5675374143);
46Eclipse RCP开发桌面程序        table.setItemCount(10);
47Eclipse RCP开发桌面程序        table.setLinesVisible(true);
48Eclipse RCP开发桌面程序        //
49Eclipse RCP开发桌面程序        createActions();
50Eclipse RCP开发桌面程序        initializeToolBar();
51Eclipse RCP开发桌面程序        initializeMenu();
52Eclipse RCP开发桌面程序            }

53Eclipse RCP开发桌面程序
54Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    /**
55Eclipse RCP开发桌面程序     * Create the actions
56Eclipse RCP开发桌面程序     */

57Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    private void createActions() {
58Eclipse RCP开发桌面程序        // Create the actions
59Eclipse RCP开发桌面程序    }

60Eclipse RCP开发桌面程序
61Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    /**
62Eclipse RCP开发桌面程序     * Initialize the toolbar
63Eclipse RCP开发桌面程序     */

64Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    private void initializeToolBar() {
65Eclipse RCP开发桌面程序        IToolBarManager toolbarManager = getViewSite().getActionBars()
66Eclipse RCP开发桌面程序                .getToolBarManager();
67Eclipse RCP开发桌面程序    }

68Eclipse RCP开发桌面程序
69Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    /**
70Eclipse RCP开发桌面程序     * Initialize the menu
71Eclipse RCP开发桌面程序     */

72Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    private void initializeMenu() {
73Eclipse RCP开发桌面程序        IMenuManager menuManager = getViewSite().getActionBars()
74Eclipse RCP开发桌面程序                .getMenuManager();
75Eclipse RCP开发桌面程序    }

76Eclipse RCP开发桌面程序
77Eclipse RCP开发桌面程序    @Override
78Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void setFocus() {
79Eclipse RCP开发桌面程序        // Set the focus
80Eclipse RCP开发桌面程序    }

81Eclipse RCP开发桌面程序
82Eclipse RCP开发桌面程序    }


其中,添加控件的代码由Disgner插件自动生成。这个时候,如果我们运行程序的话,我们的视图还不会被显示出来。为了让我们的视图可以显示,我们还需要修改Perspective.java文件,代码如下:

 1 Eclipse RCP开发桌面程序package cn.blogjava.youxia.rcp_start ;
 2 Eclipse RCP开发桌面程序
 3 Eclipse RCP开发桌面程序import org.eclipse.ui.IPageLayout ;
 4 Eclipse RCP开发桌面程序 import org.eclipse.ui.IPerspectiveFactory ;
 5 Eclipse RCP开发桌面程序
 6 Eclipse RCP开发桌面程序public class Perspective implements IPerspectiveFactory {
 7 Eclipse RCP开发桌面程序
 8 Eclipse RCP开发桌面程序    public void createInitialLayout(IPageLayout layout) {
 9 Eclipse RCP开发桌面程序        String editorArea  =  layout.getEditorArea() ;
10 Eclipse RCP开发桌面程序         layout.addView( " cn.blogjava.youxia.views.FirstView " ,  IPageLayout.RIGHT ,   0 .2f ,  editorArea) ;
11 Eclipse RCP开发桌面程序     }
12 Eclipse RCP开发桌面程序}

运行程序,得到如下效果:

Eclipse RCP开发桌面程序

我们可以发现,上面这个视图的标签不是我们通常看到的波浪形,我们可以通过配置文件的方式来更改产品的样式。
首先,在plugin.xml中对org.eclipse.core.runtime.products扩展点的属性进行更改,如下:

 1 Eclipse RCP开发桌面程序< extension
 2 Eclipse RCP开发桌面程序         id = " product "
 3 Eclipse RCP开发桌面程序         point = " org.eclipse.core.runtime.products " >
 4 Eclipse RCP开发桌面程序       < product
 5 Eclipse RCP开发桌面程序            application = " cn.blogjava.youxia.rcp_start.application "
 6 Eclipse RCP开发桌面程序            name = " 第一个RCP程序 " >
 7 Eclipse RCP开发桌面程序          < property
 8 Eclipse RCP开发桌面程序               name = " preferenceCustomization "
 9 Eclipse RCP开发桌面程序               value = " plugin_customization.ini " />
10 Eclipse RCP开发桌面程序       </ product >
11 Eclipse RCP开发桌面程序 </ extension >


可见,我们为我们的产品添加了一个prefereneCustomization属性,该属性的值为plugin_customization.ini文件,在该文件中,我们可以配置我们的样式。在这里,它的内容如下:

1 Eclipse RCP开发桌面程序org.eclipse.ui/SHOW_TRADITIONAL_STYLE_TABS = false
2 Eclipse RCP开发桌面程序org.eclipse.ui/DOCK_PERSPECTIVE_BAR = topRight


事实上,在这个文件中可以定义的参数有上百个,大家可以查看Eclipse的文档。
这个时候,效果应该是这样的了:
Eclipse RCP开发桌面程序

好 了,我们现在对以上的代码做一个总结。我不是写教科书,在Blog中也没有写得那么详细的条件。我们这里主要关注在哪个地方对代码进行扩展,可以达到我们 想要的效果。比如,我们要创建视图,就是需要扩展org.eclipse.ui.part.ViewPart类,然后向其中添加控件,再然后配置 plugin.xml文件,最后修改透视图的代码,以便它能够显示出来。

在ViewPart类中,我们添加控件的操作主要是在public void createPartControl(Composite parent)这个方法中进行,而方法最后会调用以下三个方法:
createActions();
initializeToolBar();
initializeMenu();
从这三个方法的方法名我们不难看出,它们的功能是创建视图特有的菜单栏和工具栏的,结合上一小节的内容,我们应该很快就可以探索到怎么给视图添加漂亮的工具栏了,这里我不再罗嗦。

再 来看Perspective.java,不难发现,所有的透视图类都需要实现IPerspectiveFactory接口,而该接口的 createInitialLayout方法,就是描述工作台窗口中编辑器和视图的布局。默认情况下,透视图中只包含一个编辑器区域,就是我们第一节中看 到的那个效果。在createInitialLayou中,我们可以通过以下几个方法向透视图中添加视图、编辑器和菜单:
addView   —— 添加视图
addActionSet —— 添加菜单和工具栏
createFolder —— 创建一个IForderLayou,可以让多个视图重叠在同一个位置

写 到这里,肯定有人会问,如果我要创建一个象Eclipse中的资源视图这样的视图,该怎么做呢?这我们就要感谢 org.eclipse.jface.viewers包了,Viewer,这里翻译为查看器,它和视图是不一样的。JFace查看器是Jface对SWT 部件的封装,它简化了我们对小部件的操作。在使用查看器的时候,它的数据使用单独的模型对象来保存,使用查看器的setInput方法可以为查看器设置模 型,此外,在使用查看器的时候,需要为它提供ContentProvider(内容提供器)和LabelProvider(标签提供器)。

JFace查看器主要分为以下几类:
1. ListViewer: 对应于SWT的列表控件,目的是将列表中的元素映射至SWT列表控件
2. TreeViewer: 对应于SWT的树控件,提供树的展开和折叠等基本操作
3. TableViewer: 对应于SWT的表控件,映射表中的元素
4. TextViewer: 对应于SWT的StyledText控件,创建编辑器的时候,使用这个查看器是最合适不过了。

好了,介绍性的文字就写到这里,我想大家一定已经知道了探索的方向。下面,我们看一个简单的示例,就是这篇文章开头给出的效果图。它是我模仿医院管理系统做的一个简单例子,左边的视图就是使用了一个ListView查看器。这里给出它的关键代码:

 1 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序public   void  createPartControl(Composite parent)  {
 2Eclipse RCP开发桌面程序        
 3Eclipse RCP开发桌面程序
 4Eclipse RCP开发桌面程序        viewer = new ListViewer(parent, SWT.BORDER);
 5Eclipse RCP开发桌面程序        viewer.setContentProvider(new PersonContentProvider());
 6Eclipse RCP开发桌面程序        viewer.setLabelProvider(new PersonLabelProvider());
 7Eclipse RCP开发桌面程序        viewer.setInput(new PersonModel());
 8Eclipse RCP开发桌面程序        
 9Eclipse RCP开发桌面程序        createActions();
10Eclipse RCP开发桌面程序        initializeToolBar();
11Eclipse RCP开发桌面程序        initializeMenu();
12Eclipse RCP开发桌面程序    }


可以看到,这里需要设置内容提供器和标签提供器和模型。下面,我们先创建一个病人类Person.java:

 1 Eclipse RCP开发桌面程序package  cn.blogjava.youxia.views;
 2 Eclipse RCP开发桌面程序
 3 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序 public   class  Person  {
 4Eclipse RCP开发桌面程序    
 5Eclipse RCP开发桌面程序    private String name;
 6Eclipse RCP开发桌面程序    private String sex;
 7Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public String getName() {
 8Eclipse RCP开发桌面程序        return name;
 9Eclipse RCP开发桌面程序    }

10Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void setName(String name) {
11Eclipse RCP开发桌面程序        this.name = name;
12Eclipse RCP开发桌面程序    }

13Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public String getSex() {
14Eclipse RCP开发桌面程序        return sex;
15Eclipse RCP开发桌面程序    }

16Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void setSex(String sex) {
17Eclipse RCP开发桌面程序        this.sex = sex;
18Eclipse RCP开发桌面程序    }

19Eclipse RCP开发桌面程序
20Eclipse RCP开发桌面程序}


下面,创建模型类PersonModel.java,在构造函数中我们向List中填入了几个初始化数据:

 1 Eclipse RCP开发桌面程序package  cn.blogjava.youxia.views;
 2 Eclipse RCP开发桌面程序 import  java.util.ArrayList;
 3 Eclipse RCP开发桌面程序
 4 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序 public   class  PersonModel  {
 5Eclipse RCP开发桌面程序    
 6Eclipse RCP开发桌面程序    private ArrayList<Person> list = new ArrayList<Person>();
 7Eclipse RCP开发桌面程序    
 8Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public interface Listener{
 9Eclipse RCP开发桌面程序        public void add(Person p);
10Eclipse RCP开发桌面程序        public void remove(Person p);
11Eclipse RCP开发桌面程序    }

12Eclipse RCP开发桌面程序    
13Eclipse RCP开发桌面程序    private Listener listener;
14Eclipse RCP开发桌面程序    
15Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public PersonModel(){
16Eclipse RCP开发桌面程序        //向list里面填入几个初始化数据
17Eclipse RCP开发桌面程序        Person p1 = new Person();
18Eclipse RCP开发桌面程序        p1.setName("病人1");
19Eclipse RCP开发桌面程序        p1.setSex("");
20Eclipse RCP开发桌面程序        list.add(p1);
21Eclipse RCP开发桌面程序        
22Eclipse RCP开发桌面程序        Person p2 = new Person();
23Eclipse RCP开发桌面程序        p2.setName("病人2");
24Eclipse RCP开发桌面程序        p2.setSex("");
25Eclipse RCP开发桌面程序        list.add(p2);
26Eclipse RCP开发桌面程序        
27Eclipse RCP开发桌面程序    }

28Eclipse RCP开发桌面程序
29Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void setListener(Listener listener){
30Eclipse RCP开发桌面程序        this.listener = listener;
31Eclipse RCP开发桌面程序    }

32Eclipse RCP开发桌面程序    
33Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void add(Person p){
34Eclipse RCP开发桌面程序        list.add(p);
35Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        if(listener != null){
36Eclipse RCP开发桌面程序            listener.add(p);
37Eclipse RCP开发桌面程序        }

38Eclipse RCP开发桌面程序    }

39Eclipse RCP开发桌面程序    
40Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void remove(Person p){
41Eclipse RCP开发桌面程序        list.remove(p);
42Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        if(listener != null){
43Eclipse RCP开发桌面程序            listener.remove(p);
44Eclipse RCP开发桌面程序        }

45Eclipse RCP开发桌面程序    }

46Eclipse RCP开发桌面程序    
47Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public ArrayList elements(){
48Eclipse RCP开发桌面程序        return list;
49Eclipse RCP开发桌面程序    }

50Eclipse RCP开发桌面程序}


在 这里,我们还定义了一个Listener接口,为什么要有这么一个接口呢?就是为了让我们模型中的数据被改变时,查看器能够相应更改。下面,我们实现内容 提供器,该内容提供器实现了PersonModel中定义的Listener接口,如下PersonContentProvider.java:

 1 Eclipse RCP开发桌面程序package  cn.blogjava.youxia.views;
 2 Eclipse RCP开发桌面程序
 3 Eclipse RCP开发桌面程序 import  org.eclipse.jface.viewers.IStructuredContentProvider;
 4 Eclipse RCP开发桌面程序 import  org.eclipse.jface.viewers.Viewer;
 5 Eclipse RCP开发桌面程序 import  org.eclipse.jface.viewers.ListViewer;
 6 Eclipse RCP开发桌面程序
 7 Eclipse RCP开发桌面程序 import  cn.blogjava.youxia.views.PersonModel.Listener;
 8 Eclipse RCP开发桌面程序
 9 Eclipse RCP开发桌面程序 public   class  PersonContentProvider  implements  IStructuredContentProvider,
10 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        Listener  {
11Eclipse RCP开发桌面程序
12Eclipse RCP开发桌面程序    PersonModel input;
13Eclipse RCP开发桌面程序    ListViewer viewer;
14Eclipse RCP开发桌面程序    
15Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public Object[] getElements(Object inputElement) {
16Eclipse RCP开发桌面程序        // TODO 自动生成方法存根
17Eclipse RCP开发桌面程序        return input.elements().toArray();
18Eclipse RCP开发桌面程序    }

19Eclipse RCP开发桌面程序
20Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void dispose() {
21Eclipse RCP开发桌面程序        // TODO 自动生成方法存根
22Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        if(input != null){
23Eclipse RCP开发桌面程序            input.setListener(null);
24Eclipse RCP开发桌面程序        }

25Eclipse RCP开发桌面程序        input = null;
26Eclipse RCP开发桌面程序
27Eclipse RCP开发桌面程序    }

28Eclipse RCP开发桌面程序
29Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
30Eclipse RCP开发桌面程序        // TODO 自动生成方法存根
31Eclipse RCP开发桌面程序        viewer = (ListViewer)viewer;
32Eclipse RCP开发桌面程序        input = (PersonModel)newInput;
33Eclipse RCP开发桌面程序        input.setListener(this);
34Eclipse RCP开发桌面程序
35Eclipse RCP开发桌面程序    }

36Eclipse RCP开发桌面程序
37Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void add(Person p) {
38Eclipse RCP开发桌面程序        // TODO 自动生成方法存根
39Eclipse RCP开发桌面程序        viewer.add(p);
40Eclipse RCP开发桌面程序    }

41Eclipse RCP开发桌面程序
42Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void remove(Person p) {
43Eclipse RCP开发桌面程序        // TODO 自动生成方法存根
44Eclipse RCP开发桌面程序        viewer.remove(p);
45Eclipse RCP开发桌面程序    }

46Eclipse RCP开发桌面程序
47Eclipse RCP开发桌面程序}


我们知道,列表中的元素都是Person类的对象,怎么让他们显示出来呢,需要实现标签提供器,在标签提供器中,我们可以设置对象显示的图标和文字,如下PersonLabelProvider.java:

 1 Eclipse RCP开发桌面程序package  cn.blogjava.youxia.views;
 2 Eclipse RCP开发桌面程序
 3 Eclipse RCP开发桌面程序 import  org.eclipse.jface.viewers.ILabelProvider;
 4 Eclipse RCP开发桌面程序 import  org.eclipse.jface.viewers.ILabelProviderListener;
 5 Eclipse RCP开发桌面程序 import  org.eclipse.swt.graphics.Image;
 6 Eclipse RCP开发桌面程序
 7 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序 public   class  PersonLabelProvider  implements  ILabelProvider  {
 8Eclipse RCP开发桌面程序
 9Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public Image getImage(Object element) {
10Eclipse RCP开发桌面程序        return null;
11Eclipse RCP开发桌面程序    }

12Eclipse RCP开发桌面程序
13Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public String getText(Object element) {
14Eclipse RCP开发桌面程序        // TODO 自动生成方法存根
15Eclipse RCP开发桌面程序        return ((Person)element).getName();
16Eclipse RCP开发桌面程序    }

17Eclipse RCP开发桌面程序
18Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void addListener(ILabelProviderListener listener) {
19Eclipse RCP开发桌面程序        // TODO 自动生成方法存根
20Eclipse RCP开发桌面程序
21Eclipse RCP开发桌面程序    }

22Eclipse RCP开发桌面程序
23Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void dispose() {
24Eclipse RCP开发桌面程序        // TODO 自动生成方法存根
25Eclipse RCP开发桌面程序
26Eclipse RCP开发桌面程序    }

27Eclipse RCP开发桌面程序
28Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public boolean isLabelProperty(Object element, String property) {
29Eclipse RCP开发桌面程序        // TODO 自动生成方法存根
30Eclipse RCP开发桌面程序        return false;
31Eclipse RCP开发桌面程序    }

32Eclipse RCP开发桌面程序
33Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void removeListener(ILabelProviderListener listener) {
34Eclipse RCP开发桌面程序        // TODO 自动生成方法存根
35Eclipse RCP开发桌面程序
36Eclipse RCP开发桌面程序    }

37Eclipse RCP开发桌面程序
38Eclipse RCP开发桌面程序}


运行程序,就得到了文章开头的效果,但是不能在右边的视图中显示病人的详细信息。

如果要做到视图的交互,需要添加事件的监听器。使用Java 进行GUI开发的人应该都不会陌生,而我在RCP上,也处于探索阶段,更深一步的内容,让我们自己慢慢研究吧。
================================================================================
没有嵌入Active X控件的视图:
Eclipse RCP开发桌面程序

嵌入浏览器控件,并显示www.blogjava.net的主页:
Eclipse RCP开发桌面程序

在Windows 系统下,OLE和Active X控件是两个非常吸引人的技术,它们的基础都是COM。OLE的体验,就是平时我们可以把Excel表格嵌入Word文档,或者把PDF嵌入浏览器显示一 样,而Active X控件更是无处不在,做VB开发和网页开发的人都应该很熟悉。使用Windows系统中丰富的Active X控件资源,我们可以实现功能非常强大的程序。

在Windows平台下,SWT图形工具包提供了对OLE的支持,Active X控件和OLE文档都可以被很方便地嵌入SWT窗口部件或者JFace部件,在这里,我只讨论将Active X控件插入视图。

在 一个视图中包含一个Active X控件需要两个对象的支持,即一个OleFrame和一个OleClientSite对象。如果需要创建一个OLE应用,需要先后创建他们。创建 OleFrame对象比较简单,OleFrame类定义在org.eclipse.swt.ole.win32中,创建OleFrame对象只需要简单的 new就可以,如下:

1 Eclipse RCP开发桌面程序OleFrame frame  =   new  OleFrame(parent, SWT.NONE);

在这个构造函数中,第一个参数指的是该OleFrame的母窗口部件,即Active X控件将要被嵌入的窗口部件。

在OleFrame 的基础上就可以创建OleClientSite对象,创建该对象需要知道控件的programID,这个ID的信息存放在windows的注册表中。在我 们这篇文章的例子中,我们使用的是一个浏览器控件,那么我们怎么知道浏览器控件的ProgID呢?我使用的是Visual Studio 2003自带的OleView工具,如下图:
Eclipse RCP开发桌面程序

可以看到,Microsoft Web 浏览器的ProgID为Shell.Explorer.2,我们可以这样创建OleClientSite对象:

1 Eclipse RCP开发桌面程序OleClientSite client  =   new  OleClientSite(frame,SWT.NONE, " Shell.Explorer.2 " );


创建对象后,还需要激活,才能够在RCP程序中对这些OLE对象进行操作。如下:

Eclipse RCP开发桌面程序client.doVerb(OLE.OLEIVERB_SHOW);


然后,我们需要操作这个Active X控件,调用它的方法,或者设置它的属性。比如在此例中,我们需要调用浏览器控件的navigate方法,以便我们的浏览器控件显示www.blogjava.net的主页。对Active X控件的操作通过OleAutomation对象来实现,创建OleAutomation对象的方法如下:

Eclipse RCP开发桌面程序OleAutomation automation  =   new  OleAutomation(client);

再 通过automation.invoke()来调用Active X控件的方法,其中invoke方法有几种重载形式,有只带一个int参数的,也有带int和Variant[]两个参数的,其中的int参数表示要调用 的Active X控件的方法的ID,Variant[]参数就是要传递给Active X控件的方法的参数。

这里我们要说一说Variant类,这个类提供了多个构造函数,可以方便的将int,float,long,double,string等等基本数据类型封装为Variant,比如我们要传递给浏览器控件的navigate方法的地址参数:

Eclipse RCP开发桌面程序Variant url  =   new  Variant( " http://www.blogjava.net " );


那么我们怎么才能得到Active X控件的方法的ID,还有它需要哪些参数呢?还是要借助前面提到的OleView.exe工具,如下图:
Eclipse RCP开发桌面程序

Eclipse RCP开发桌面程序

可以看到,Navigate方法的id为0x00000068,转化为十进制就是104,而它需要的参数第一个是一个字符串,其它的都是可选的,因此,我们可以这样调用它的方法:

Eclipse RCP开发桌面程序Variant url  =   new  Variant( " http://www.blogjava.net/ " );
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序automation.invoke(
104 new  Variant[] {url} );


下面,贴出本文例子中的视图的代码和菜单Action的代码,在写这篇文章之前,我一直在探索怎样从菜单控制视图,后来发现是这样:
 window.getActivePage.getViewReferences();
虽然我不知道Eclipse中Page的概念究竟是什么,但是只要能找到我要操作的视图就可以了。视图的代码如下:

OleView.java

 1 Eclipse RCP开发桌面程序package  cn.blogjava.youxia.views;
 2 Eclipse RCP开发桌面程序
 3 Eclipse RCP开发桌面程序 import  org.eclipse.jface.action.IMenuManager;
 4 Eclipse RCP开发桌面程序 import  org.eclipse.jface.action.IToolBarManager;
 5 Eclipse RCP开发桌面程序 import  org.eclipse.swt.SWT;
 6 Eclipse RCP开发桌面程序 import  org.eclipse.swt.widgets.Composite;
 7 Eclipse RCP开发桌面程序 import  org.eclipse.ui.part.ViewPart;
 8 Eclipse RCP开发桌面程序 import  org.eclipse.swt.ole.win32.OleFrame;
 9 Eclipse RCP开发桌面程序
10 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序 public   class  OleView  extends  ViewPart  {
11Eclipse RCP开发桌面程序    public OleFrame frame;
12Eclipse RCP开发桌面程序
13Eclipse RCP开发桌面程序    public static final String ID = "cn.blogjava.youxia.views.OleView"//$NON-NLS-1$
14Eclipse RCP开发桌面程序
15Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    /**
16Eclipse RCP开发桌面程序     * Create contents of the view part
17Eclipse RCP开发桌面程序     * @param parent
18Eclipse RCP开发桌面程序     */

19Eclipse RCP开发桌面程序    @Override
20Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void createPartControl(Composite parent) {
21Eclipse RCP开发桌面程序        frame = new OleFrame(parent, SWT.NONE);
22Eclipse RCP开发桌面程序        
23Eclipse RCP开发桌面程序        //
24Eclipse RCP开发桌面程序        createActions();
25Eclipse RCP开发桌面程序        initializeToolBar();
26Eclipse RCP开发桌面程序        initializeMenu();
27Eclipse RCP开发桌面程序    }

28Eclipse RCP开发桌面程序
29Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    /**
30Eclipse RCP开发桌面程序     * Create the actions
31Eclipse RCP开发桌面程序     */

32Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    private void createActions() {
33Eclipse RCP开发桌面程序        // Create the actions
34Eclipse RCP开发桌面程序    }

35Eclipse RCP开发桌面程序
36Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    /**
37Eclipse RCP开发桌面程序     * Initialize the toolbar
38Eclipse RCP开发桌面程序     */

39Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    private void initializeToolBar() {
40Eclipse RCP开发桌面程序        IToolBarManager toolbarManager = getViewSite().getActionBars()
41Eclipse RCP开发桌面程序                .getToolBarManager();
42Eclipse RCP开发桌面程序    }

43Eclipse RCP开发桌面程序
44Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    /**
45Eclipse RCP开发桌面程序     * Initialize the menu
46Eclipse RCP开发桌面程序     */

47Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    private void initializeMenu() {
48Eclipse RCP开发桌面程序        IMenuManager menuManager = getViewSite().getActionBars()
49Eclipse RCP开发桌面程序                .getMenuManager();
50Eclipse RCP开发桌面程序    }

51Eclipse RCP开发桌面程序
52Eclipse RCP开发桌面程序    @Override
53Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void setFocus() {
54Eclipse RCP开发桌面程序        // Set the focus
55Eclipse RCP开发桌面程序    }

56Eclipse RCP开发桌面程序
57Eclipse RCP开发桌面程序}

58 Eclipse RCP开发桌面程序


在这个视图中,我创建了OleFrame对象,并让它是public的,至于OleClientSite和OleAutomation对象,我们在点击菜单项后创建。菜单动作的代码如下:

OpenFileAction.java

 1 Eclipse RCP开发桌面程序package  cn.blogjava.youxia.actions;
 2 Eclipse RCP开发桌面程序
 3 Eclipse RCP开发桌面程序
 4 Eclipse RCP开发桌面程序 import  org.eclipse.jface.action.IAction;
 5 Eclipse RCP开发桌面程序 import  org.eclipse.jface.viewers.ISelection;
 6 Eclipse RCP开发桌面程序 import  org.eclipse.swt.SWT;
 7 Eclipse RCP开发桌面程序 import  org.eclipse.swt.ole.win32.OLE;
 8 Eclipse RCP开发桌面程序 import  org.eclipse.swt.ole.win32.OleClientSite;
 9 Eclipse RCP开发桌面程序 import  org.eclipse.ui.IWorkbenchWindow;
10 Eclipse RCP开发桌面程序 import  org.eclipse.ui.IWorkbenchWindowActionDelegate;
11 Eclipse RCP开发桌面程序 import  org.eclipse.ui. * ;
12 Eclipse RCP开发桌面程序 import  cn.blogjava.youxia.views. * ;
13 Eclipse RCP开发桌面程序 import  org.eclipse.swt.ole.win32.OleAutomation;
14 Eclipse RCP开发桌面程序 import  org.eclipse.swt.ole.win32.Variant;
15 Eclipse RCP开发桌面程序
16 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序 public   class  OpenFileAction  implements  IWorkbenchWindowActionDelegate  {
17Eclipse RCP开发桌面程序
18Eclipse RCP开发桌面程序    IWorkbenchWindow window;
19Eclipse RCP开发桌面程序    
20Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void dispose() {
21Eclipse RCP开发桌面程序        // TODO 自动生成方法存根
22Eclipse RCP开发桌面程序
23Eclipse RCP开发桌面程序    }

24Eclipse RCP开发桌面程序
25Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void init(IWorkbenchWindow window) {
26Eclipse RCP开发桌面程序        // TODO 自动生成方法存根
27Eclipse RCP开发桌面程序        this.window = window;
28Eclipse RCP开发桌面程序
29Eclipse RCP开发桌面程序    }

30Eclipse RCP开发桌面程序
31Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void run(IAction action) {
32Eclipse RCP开发桌面程序        // TODO 自动生成方法存根
33Eclipse RCP开发桌面程序        
34Eclipse RCP开发桌面程序        IViewReference[] vfs = window.getActivePage().getViewReferences();
35Eclipse RCP开发桌面程序        IViewPart vw;
36Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        for(int i=0; i<vfs.length; i++){
37Eclipse RCP开发桌面程序             vw = vfs[i].getView(false);
38Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序             if(vw.getTitle().equals("使用Active X控件")){
39Eclipse RCP开发桌面程序                    OleClientSite client = new OleClientSite(((OleView)vw).frame,SWT.NONE,"Shell.Explorer.2");
40Eclipse RCP开发桌面程序                    client.doVerb(OLE.OLEIVERB_SHOW);
41Eclipse RCP开发桌面程序                    OleAutomation oa = new OleAutomation(client);
42Eclipse RCP开发桌面程序                    Variant str = new Variant("http://www.blogjava.net/");
43Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序                    oa.invoke(104new Variant[]{str});
44Eclipse RCP开发桌面程序        
45Eclipse RCP开发桌面程序             }

46Eclipse RCP开发桌面程序        }

47Eclipse RCP开发桌面程序        
48Eclipse RCP开发桌面程序    }

49Eclipse RCP开发桌面程序
50Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    public void selectionChanged(IAction action, ISelection selection) {
51Eclipse RCP开发桌面程序        // TODO 自动生成方法存根
52Eclipse RCP开发桌面程序
53Eclipse RCP开发桌面程序    }

54Eclipse RCP开发桌面程序
55Eclipse RCP开发桌面程序}

56 Eclipse RCP开发桌面程序


根据前面几节将的内容配置plugin.xml和修改Perspective.java的代码,就可以看到文章开头的效果了。
================================================================================

看完这篇文章,可以实现如下界面:
Eclipse RCP开发桌面程序

Eclipse RCP开发桌面程序


当 我第一次看到RCP的时候,我就梦想着有一天能够用它开发界面华丽的2D和3D程序,经历过前面的探索,今天终于可以揭开2D绘图的神秘面纱。在包资源管 理器的插件依赖项中,我们一眼就可以看到org.eclipse.swt.graphics包,毫无疑问,和2D绘图有关的类就在这个包中。还有一个 org.eclipse.swt.opengl包也很引人注目,但是里面却只有GLCanvas类和GLData类,怎么也找不到传说中的GL类和GLU 类,也许下一篇文章我会写出关于3D的内容,但也许这个计划会夭折。

我刚开始发现org.eclipse.swt.graphics包的时 候,要使用包里面的类却不是那么容易。比如,从名称上可以看出Image类是处理图像的,但是它的构造函数无一例外都需要一个Device参数,于是,我 迷惑了,Device,我该如何取得?再比如,GC类里面含有各种绘图的方法,但是GC的构造函数需要Drawable参数,那Drawable我又该如 何获得呢?

于是,我在网上搜索关于SWT 2D方面的内容,终于,让我看到了别人这样构造Image和GC:
Image img = new Image(display,"pic.gif");
GC gc = new GC(Image);
你能看出什么?为什么display是Device的子类?为什么Image是Drawabe的子类?最简单的办法,使用Eclipse的类层次结构视图查看:

Eclipse RCP开发桌面程序

高, 实在是高,在这里我不得不佩服SWT的设计者,在一开始,他们就把所有的控件都设计为可绘制的,而且使用Device来抽象绘图的设备。从图中可以看出, 所有的控件都实现Drawable接口,Image也实现Drawable接口,而Device的子类Display和Printer刚好分别代表了屏幕 和打印机。所有的谜团都在这里解决了,我们可以使用任何控件作为GC构造函数的参数来构造GC,然后绘图,而所有需要Device参数的地方,我们可以根 据我们需要输出的设备是显示器还是打印机而分别选择Display或Printer。

在org.eclipse.swt.widgets包中,有一个Canvas类,不难看出,如果我们要绘图,这个控件是最佳选择了。在下面的代码中,我们可以通过选择不同的菜单,分别绘制椭圆,矩形,填充渐变色的矩形和一个图像,运行效果就是文章开头的图片。

视图CanvasView.java

 1 Eclipse RCP开发桌面程序package  cn.blogjava.youxia.views;
 2 Eclipse RCP开发桌面程序
 3 Eclipse RCP开发桌面程序 import  org.eclipse.swt.widgets.Composite;
 4 Eclipse RCP开发桌面程序 import  org.eclipse.ui.part.ViewPart;
 5 Eclipse RCP开发桌面程序 import  org.eclipse.swt.widgets.Canvas;
 6 Eclipse RCP开发桌面程序 import  org.eclipse.swt.SWT;
 7 Eclipse RCP开发桌面程序 import  org.eclipse.swt.events. * ;
 8 Eclipse RCP开发桌面程序 import  org.eclipse.swt.graphics.Image;
 9 Eclipse RCP开发桌面程序 import  org.eclipse.ui.PlatformUI;
10 Eclipse RCP开发桌面程序
11 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序 public   class  CanvasView  extends  ViewPart  {
12 Eclipse RCP开发桌面程序
13 Eclipse RCP开发桌面程序     public  Canvas canvas;
14 Eclipse RCP开发桌面程序    @Override
15 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public   void  createPartControl(Composite parent)  {
16 Eclipse RCP开发桌面程序         //  TODO 自动生成方法存根
17 Eclipse RCP开发桌面程序        canvas  =   new  Canvas(parent,SWT.NONE);
18 Eclipse RCP开发桌面程序            }

19 Eclipse RCP开发桌面程序
20 Eclipse RCP开发桌面程序    @Override
21 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public   void  setFocus()  {
22 Eclipse RCP开发桌面程序         //  TODO 自动生成方法存根
23 Eclipse RCP开发桌面程序
24 Eclipse RCP开发桌面程序    }

25 Eclipse RCP开发桌面程序
26 Eclipse RCP开发桌面程序}

27 Eclipse RCP开发桌面程序

菜单项绘制椭圆DrawOvalAction.java的关键部分:

 1 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序public   void  run(IAction action)  {
 2 Eclipse RCP开发桌面程序         //  TODO 自动生成方法存根
 3 Eclipse RCP开发桌面程序        IViewReference[] vfs  =  window.getActivePage().getViewReferences();
 4 Eclipse RCP开发桌面程序        IViewPart vw;
 5 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序         for ( int  i = 0 ; i < vfs.length; i ++ ) {
 6 Eclipse RCP开发桌面程序             vw  =  vfs[i].getView( false );
 7 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序              if (vw.getTitle().equals( " 画图板 " )) {
 8 Eclipse RCP开发桌面程序                     GC gc  =   new  GC(((CanvasView)vw).canvas);
 9 Eclipse RCP开发桌面程序                     gc.drawOval( 80 50 100 100 );
10 Eclipse RCP开发桌面程序                     gc.dispose();
11 Eclipse RCP开发桌面程序             }

12 Eclipse RCP开发桌面程序        }

13 Eclipse RCP开发桌面程序    }

菜单项绘制矩形DrawRectAction.java的关键部分:

 1 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序public   void  run(IAction action)  {
 2 Eclipse RCP开发桌面程序         //  TODO 自动生成方法存根
 3 Eclipse RCP开发桌面程序        IViewReference[] vfs  =  window.getActivePage().getViewReferences();
 4 Eclipse RCP开发桌面程序        IViewPart vw;
 5 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序         for ( int  i = 0 ; i < vfs.length; i ++ ) {
 6 Eclipse RCP开发桌面程序             vw  =  vfs[i].getView( false );
 7 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序              if (vw.getTitle().equals( " 画图板 " )) {
 8 Eclipse RCP开发桌面程序                     GC gc  =   new  GC(((CanvasView)vw).canvas);
 9 Eclipse RCP开发桌面程序                     gc.drawRectangle( 280 50 100 100 );
10 Eclipse RCP开发桌面程序                     gc.dispose();
11 Eclipse RCP开发桌面程序             }

12 Eclipse RCP开发桌面程序        }

13 Eclipse RCP开发桌面程序
14 Eclipse RCP开发桌面程序    }

菜单项绘制渐变矩形DrawGradientAction.java的关键部分:

 1 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序public   void  run(IAction action)  {
 2 Eclipse RCP开发桌面程序         //  TODO 自动生成方法存根
 3 Eclipse RCP开发桌面程序        IViewReference[] vfs  =  window.getActivePage().getViewReferences();
 4 Eclipse RCP开发桌面程序        IViewPart vw;
 5 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序         for ( int  i = 0 ; i < vfs.length; i ++ ) {
 6 Eclipse RCP开发桌面程序             vw  =  vfs[i].getView( false );
 7 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序              if (vw.getTitle().equals( " 画图板 " )) {
 8 Eclipse RCP开发桌面程序                     GC gc  =   new  GC(((CanvasView)vw).canvas);
 9 Eclipse RCP开发桌面程序                     gc.setBackground(window.getShell().getDisplay().getSystemColor(SWT.COLOR_BLUE));
10 Eclipse RCP开发桌面程序                     gc.fillGradientRectangle( 80 , 200 , 100 , 100 , false ); 
11 Eclipse RCP开发桌面程序
12 Eclipse RCP开发桌面程序                     gc.dispose();
13 Eclipse RCP开发桌面程序             }

14 Eclipse RCP开发桌面程序        }

15 Eclipse RCP开发桌面程序
16 Eclipse RCP开发桌面程序    }

菜单项绘制图像DrawImageAction.java的关键部分:

 1 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序public   void  run(IAction action)  {
 2 Eclipse RCP开发桌面程序         //  TODO 自动生成方法存根
 3 Eclipse RCP开发桌面程序        IViewReference[] vfs  =  window.getActivePage().getViewReferences();
 4 Eclipse RCP开发桌面程序        IViewPart vw;
 5 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序         for ( int  i = 0 ; i < vfs.length; i ++ ) {
 6 Eclipse RCP开发桌面程序             vw  =  vfs[i].getView( false );
 7 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序              if (vw.getTitle().equals( " 画图板 " )) {
 8 Eclipse RCP开发桌面程序                     GC gc  =   new  GC(((CanvasView)vw).canvas);
 9 Eclipse RCP开发桌面程序                     Image img  =   new  Image(window.getShell().getDisplay(), " E://img.gif " );
10 Eclipse RCP开发桌面程序                     gc.drawImage(img,  280 200 );
11 Eclipse RCP开发桌面程序                     gc.dispose();
12 Eclipse RCP开发桌面程序             }

13 Eclipse RCP开发桌面程序        }

14 Eclipse RCP开发桌面程序
15 Eclipse RCP开发桌面程序    }


上 面的方法虽然实现了绘图,但是还有一个问题,就是一旦我们的窗口最小化或者被别的窗口遮挡后,图形就会消失。原因其实很简单,一旦我们的窗口最小化或者被 别的窗口遮挡后,控件就需要重画,所以我们画的图形就不见了,如果要让控件重画的时候也能绘制图形,就应该使用 canvas.addPaintListener()为控件添加Paint事件的监听器。示例代码见下。

 1 Eclipse RCP开发桌面程序package  cn.blogjava.youxia.views;
 2 Eclipse RCP开发桌面程序
 3 Eclipse RCP开发桌面程序 import  org.eclipse.swt.widgets.Composite;
 4 Eclipse RCP开发桌面程序 import  org.eclipse.ui.part.ViewPart;
 5 Eclipse RCP开发桌面程序 import  org.eclipse.swt.widgets.Canvas;
 6 Eclipse RCP开发桌面程序 import  org.eclipse.swt.SWT;
 7 Eclipse RCP开发桌面程序 import  org.eclipse.swt.events. * ;
 8 Eclipse RCP开发桌面程序 import  org.eclipse.swt.graphics.Image;
 9 Eclipse RCP开发桌面程序 import  org.eclipse.ui.PlatformUI;
10 Eclipse RCP开发桌面程序
11 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序 public   class  CanvasView  extends  ViewPart  {
12 Eclipse RCP开发桌面程序
13 Eclipse RCP开发桌面程序     public  Canvas canvas;
14 Eclipse RCP开发桌面程序    @Override
15 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public   void  createPartControl(Composite parent)  {
16 Eclipse RCP开发桌面程序         //  TODO 自动生成方法存根
17 Eclipse RCP开发桌面程序        canvas  =   new  Canvas(parent,SWT.NONE);
18 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        canvas.addPaintListener( new  PaintListener()  {
19 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序             public   void  paintControl(PaintEvent e)  {
20 Eclipse RCP开发桌面程序                 // 画椭圆
21 Eclipse RCP开发桌面程序                e.gc.drawOval( 80 50 100 100 );
22 Eclipse RCP开发桌面程序                 // 画矩形
23 Eclipse RCP开发桌面程序                e.gc.drawRectangle( 280 50 100 100 );
24 Eclipse RCP开发桌面程序                 // 画渐变矩形
25 Eclipse RCP开发桌面程序                e.gc.setBackground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_BLUE));
26 Eclipse RCP开发桌面程序                 e.gc.fillGradientRectangle( 80 , 200 , 100 , 100 , false );
27 Eclipse RCP开发桌面程序                  // 画图形
28 Eclipse RCP开发桌面程序                 Image img  =   new  Image(PlatformUI.getWorkbench().getDisplay(), " E://img.gif " );
29 Eclipse RCP开发桌面程序                 e.gc.drawImage(img,  280 200 );
30 Eclipse RCP开发桌面程序
31 Eclipse RCP开发桌面程序        }

32 Eclipse RCP开发桌面程序        }
);
33 Eclipse RCP开发桌面程序    }

34 Eclipse RCP开发桌面程序
35 Eclipse RCP开发桌面程序    @Override
36 Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序     public   void  setFocus()  {
37 Eclipse RCP开发桌面程序         //  TODO 自动生成方法存根
38 Eclipse RCP开发桌面程序
39 Eclipse RCP开发桌面程序    }

40 Eclipse RCP开发桌面程序
41 Eclipse RCP开发桌面程序}

42 Eclipse RCP开发桌面程序

GC类的绘图方法很多,而且可以设置不同的前景色,背景色,画笔,画刷等等,还可以裁减图形,这些就靠我们慢慢探索了。
===========================================================================================
看完这一篇,我们应该可以使用OpenGL绘制如下图的场景了。该场景是一个旋转的三菱锥矩阵,下面是旋转到不同方位的截图:
Eclipse RCP开发桌面程序

Eclipse RCP开发桌面程序

Eclipse RCP开发桌面程序

我整整花了一个星期的时间来研究SWT中的OpenGL,遇到的第一个困难是找不到传说中的GL类和GLU类,最后,通过搜索引擎终于找到了,原来使用Eclipse进行OpenGL开发,还需要另外下载OpenGL插件,如下图:
Eclipse RCP开发桌面程序

这里有OpenGL的类库,还有一个示例,把类库下载下来,解压,放到Eclipse的Plugin目录下,然后在我们的项目中添加依赖项,就可以看到我们需要使用的类了,如下图:
Eclipse RCP开发桌面程序

我们需要对OpenGL编程的一些基本概念有点了解,在OpenGL中,3D场景不是直接绘制到操作系统的窗口上的,而是有一个称为着色描述表(Rendering Context)的东西,我们这里简称它为context,OpenGL的绘图命令都是在当前context上进行绘制,然后再把它渲染到操作系统的设备描述表(Device Context)上,这里,我们可以简单的理解成把它渲染到窗口控件上(其实也可以渲染到全屏幕)。

在Windows中使用OpenGL编程比较麻烦,因为我们需要设置一个叫做象素格式的东西,大家只要看看下面的这段C代码,就知道我为什么说它麻烦了:

Eclipse RCP开发桌面程序if  ( ! (PixelFormat = ChoosePixelFormat(hDC, & pfd)))    //  Windows 找到相应的象素格式了吗?
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序
     {
Eclipse RCP开发桌面程序        KillGLWindow();               
// 重置显示区
Eclipse RCP开发桌面程序
        MessageBox(NULL,"Can't Find A Suitable PixelFormat.",
Eclipse RCP开发桌面程序            
"ERROR",MB_OK|MB_ICONEXCLAMATION);
Eclipse RCP开发桌面程序        
return FALSE;                // 返回 FALSE
Eclipse RCP开发桌面程序
    }

Eclipse RCP开发桌面程序
Eclipse RCP开发桌面程序if ( ! SetPixelFormat(hDC,PixelFormat, & pfd))       //  能够设置象素格式么?
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序
     {
Eclipse RCP开发桌面程序        KillGLWindow();               
// 重置显示区
Eclipse RCP开发桌面程序
        MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
Eclipse RCP开发桌面程序        
return FALSE;                // 返回 FALSE
Eclipse RCP开发桌面程序
    }

Eclipse RCP开发桌面程序
Eclipse RCP开发桌面程序if  ( ! (hRC = wglCreateContext(hDC)))          //  能否取得着色描述表?
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序
     {
Eclipse RCP开发桌面程序        KillGLWindow();              
// 重置显示区
Eclipse RCP开发桌面程序
        MessageBox(NULL,"Can't Create A GL Rendering Context.",
Eclipse RCP开发桌面程序           
"ERROR",MB_OK|MB_ICONEXCLAMATION);
Eclipse RCP开发桌面程序        
return FALSE;               // 返回 FALSE
Eclipse RCP开发桌面程序
    }

Eclipse RCP开发桌面程序


在SWT 中,我们开发OpenGL应用就要简单得多,这全部要归功于org.eclipse.swt.opengl包下面的GLCanvas类和GLData类, 使用GLCanvas类可以直接创建一个用于OpenGL渲染的控件,至于设置象素格式这样复杂的问题,它已经帮我们解决了,不信你看GLCanvas类 的构造函数的实现。

GLCanvas类中的几个方法代表了我一开始提到的OpenGL的几个基本概念,setCurrent()方法就是 为了把该控件的context设置为OpenGL的当前着色描述表,然后使用GL和GLU类中的方法在当前context上进行绘图,绘制完图形以后,再 使用GLCanvas类的swapBuffers()方法交换缓冲区,也就是把context中的3D场景渲染到控件上。

写到这里,大家肯定认为一切问题都应该迎刃而解了,然而,我却碰到了另外一个困难,这个困难就是SWT的OpenGL表现怪异,怎么个怪异呢?请看下面视图类的代码:

Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序public   void  createPartControl(Composite parent)  {
Eclipse RCP开发桌面程序        
// TODO 自动生成方法存根
Eclipse RCP开发桌面程序
        GLData data = new GLData();
Eclipse RCP开发桌面程序        data.depthSize 
= 1;
Eclipse RCP开发桌面程序        data.doubleBuffer 
= true;
Eclipse RCP开发桌面程序        GLCanvas canvas 
= new GLCanvas(parent, SWT.NO_BACKGROUND, data);
Eclipse RCP开发桌面程序        
//设置该canvas的context为OpenGL的当前context
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序
        if(!canvas.isCurrent()){
Eclipse RCP开发桌面程序            canvas.setCurrent();
Eclipse RCP开发桌面程序        }

Eclipse RCP开发桌面程序        
//这里可以进行OpenGL绘图
Eclipse RCP开发桌面程序        
Eclipse RCP开发桌面程序        
//交换缓存,将图形渲染到控件上
Eclipse RCP开发桌面程序
        canvas.swapBuffers();
Eclipse RCP开发桌面程序    }


按道理,我们应该可以得到一个经典的3D的黑色场景,但是,我得到的却是这样的效果:
Eclipse RCP开发桌面程序

相 当的郁闷啊,就是这个问题困扰了我至少一个星期。我把官方网站上的示例看了有看,就是找不到问题的关键所在。直到最后,我用了另外一个线程,每100ms 都调用canvas.swapBuffers()把场景渲染一遍问题才解决。由此可见,之所以回出现上面的问题,主要是因为我们渲染的场景很快会被操作系 统的其他绘图操作所覆盖,只有不断的渲染我们才能看到连续的3D图形。

我是这样实现让3D场景连续渲染的:

Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序public   void  createPartControl(Composite parent)  {
Eclipse RCP开发桌面程序        
// TODO 自动生成方法存根
Eclipse RCP开发桌面程序
        GLData data = new GLData();
Eclipse RCP开发桌面程序        data.depthSize 
= 1;
Eclipse RCP开发桌面程序        data.doubleBuffer 
= true;
Eclipse RCP开发桌面程序        GLCanvas canvas 
= new GLCanvas(parent, SWT.NO_BACKGROUND, data);
Eclipse RCP开发桌面程序        
//将绘图代码转移到定时器中
Eclipse RCP开发桌面程序
        Refresher rf = new Refresher(canvas);
Eclipse RCP开发桌面程序        rf.run();
Eclipse RCP开发桌面程序    }


Refresher类的代码如下:

Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序class  Refresher  implements  Runnable  {
Eclipse RCP开发桌面程序    
public static final int DELAY = 100;
Eclipse RCP开发桌面程序    
Eclipse RCP开发桌面程序    
private GLCanvas canvas;
Eclipse RCP开发桌面程序    
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    
public Refresher(GLCanvas canvas) {
Eclipse RCP开发桌面程序        
this.canvas = canvas;
Eclipse RCP开发桌面程序    }

Eclipse RCP开发桌面程序    
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    
public void run() {
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        
if (this.canvas != null && !this.canvas.isDisposed()) {
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序            
if(!canvas.isCurrent()){
Eclipse RCP开发桌面程序                canvas.setCurrent();
Eclipse RCP开发桌面程序            }

Eclipse RCP开发桌面程序            
//这里添加OpenGL绘图代码
Eclipse RCP开发桌面程序
            canvas.swapBuffers();
Eclipse RCP开发桌面程序            
this.canvas.getDisplay().timerExec(DELAY, this);
Eclipse RCP开发桌面程序        }

Eclipse RCP开发桌面程序    }

Eclipse RCP开发桌面程序  
Eclipse RCP开发桌面程序}


问题解决,得到的效果图如下:
Eclipse RCP开发桌面程序

OK,下面的任务就是完完全全的使用OpenGL的绘图功能了,不管你的OpenGL教材使用的是什么操作系统什么编程语言,你都能很简单的把它的概念拿到这里来使用。

使用OpenGL的第一件事,就是要设置投影矩阵、透视图和观察者矩阵,如果你不知道为什么要这么做,请查看OpenGL的基础教材,在这里,照搬就行了。为了让我们的控件在每次改变大小的时候都能够做这些设置,我们使用事件监听器,如下:

Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序public   void  createPartControl(Composite parent)  {
Eclipse RCP开发桌面程序        
// TODO 自动生成方法存根
Eclipse RCP开发桌面程序
        GLData data = new GLData();
Eclipse RCP开发桌面程序        data.depthSize 
= 1;
Eclipse RCP开发桌面程序        data.doubleBuffer 
= true;
Eclipse RCP开发桌面程序        canvas 
= new GLCanvas(parent, SWT.NO_BACKGROUND, data);
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        canvas.addControlListener(
new ControlAdapter() {
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序            
public void controlResized(ControlEvent e) {
Eclipse RCP开发桌面程序                Rectangle rect 
= canvas.getClientArea();
Eclipse RCP开发桌面程序                GL.glViewport(
00, rect.width, rect.height);
Eclipse RCP开发桌面程序                
Eclipse RCP开发桌面程序                
//选择投影矩阵
Eclipse RCP开发桌面程序
                GL.glMatrixMode(GL.GL_PROJECTION);
Eclipse RCP开发桌面程序                
//重置投影矩阵
Eclipse RCP开发桌面程序
                GL.glLoadIdentity();
Eclipse RCP开发桌面程序                
//设置窗口比例和透视图
Eclipse RCP开发桌面程序
                GLU.gluPerspective(45.0f, (float) rect.width / (float) rect.height, 0.1f100.0f);
Eclipse RCP开发桌面程序                
//选择模型观察矩阵
Eclipse RCP开发桌面程序
                GL.glMatrixMode(GL.GL_MODELVIEW);
Eclipse RCP开发桌面程序                
//重置模型观察矩阵
Eclipse RCP开发桌面程序
                GL.glLoadIdentity();
Eclipse RCP开发桌面程序                
Eclipse RCP开发桌面程序                
//黑色背景
Eclipse RCP开发桌面程序
                GL.glClearColor(0.0f0.0f0.0f0.0f);
Eclipse RCP开发桌面程序                
//设置深度缓存
Eclipse RCP开发桌面程序
                GL.glClearDepth(1.0f);
Eclipse RCP开发桌面程序                
//启动深度测试
Eclipse RCP开发桌面程序
                GL.glEnable(GL.GL_DEPTH_TEST);
Eclipse RCP开发桌面程序                
//选择深度测试类型
Eclipse RCP开发桌面程序
                GL.glDepthFunc(GL.GL_LESS);
Eclipse RCP开发桌面程序                
//启用阴影平滑
Eclipse RCP开发桌面程序
                GL.glShadeModel(GL.GL_SMOOTH);
Eclipse RCP开发桌面程序                
//精细修正透视图
Eclipse RCP开发桌面程序
                GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
Eclipse RCP开发桌面程序                
//清除屏幕和深度缓存
Eclipse RCP开发桌面程序
                GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
Eclipse RCP开发桌面程序                
//重置当前的模型观察矩阵
Eclipse RCP开发桌面程序
                GL.glLoadIdentity();
Eclipse RCP开发桌面程序            }

Eclipse RCP开发桌面程序        }
);  
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        canvas.addDisposeListener(
new DisposeListener() {
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序            
public void widgetDisposed(DisposeEvent e) {
Eclipse RCP开发桌面程序                dispose();
Eclipse RCP开发桌面程序            }

Eclipse RCP开发桌面程序        }
);



调用glLoadIdentity()之后,实际上将当前点移到了屏幕中心,X坐标轴从左至右,Y坐标轴从下至上,Z坐标轴从里至外。OpenGL屏幕中心的坐标值是XY轴上的 0.0f 点。中心左面的坐标值是负值,右面是正值。移向屏幕顶端是正值,移向屏幕底端是负值。移入屏幕深处是负值,移出屏幕则是正值。

glTranslatef(x, y, z)是将当前点沿着XYZ轴移动,当我们绘图的时候,不是相对于屏幕中间,而是相对于当前点。

glBegin(GL.GL_TRIANGLES)的意思是开始绘制三角形,glEnd()告诉OpenGL三角形已经创建好了。通常当我们需要画3个顶点时,可以使用GL_TRIANGLES。在绝大多数的显卡上,绘制三角形是相当快速的。如果要画四个顶点,使用GL_QUADS的话会更方便。但据我所知,绝大多数的显卡都使用三角形来为对象着色。最后,如果想要画更多的顶点时,可以使用GL_POLYGON

glVertex(x,y,z)用来设置顶点,如果绘制三角形,这些顶点需要三个一组,如果绘制四边形,则是四个为一组。如果我们要为顶点着色,就需要glColor 3f (r,g,b)方法,记住,每次设置以后,这个颜色就是当前颜色,直到再次调用该方法重新设置为止。

最后需要介绍的是glRotatef(Angle,Xvector,Yvector,Zvector)方法,该方法负责让对象围绕指定的轴旋转,Angle参数指转动的角度,注意是浮点数哦。

下面是我的视图类的全部代码,我把3D绘图的任务全部放到了另外一个线程中,并且定义了一个递归方法public void drawPyramid(float x, float y, float z, int n)用来绘制三菱锥矩阵。如下:

Eclipse RCP开发桌面程序package  cn.blogjava.youxia.views;
Eclipse RCP开发桌面程序
Eclipse RCP开发桌面程序
import  org.eclipse.opengl.GL;
Eclipse RCP开发桌面程序
import  org.eclipse.opengl.GLU;
Eclipse RCP开发桌面程序
import  org.eclipse.swt.events.ControlAdapter;
Eclipse RCP开发桌面程序
import  org.eclipse.swt.events.ControlEvent;
Eclipse RCP开发桌面程序
import  org.eclipse.swt.events.DisposeEvent;
Eclipse RCP开发桌面程序
import  org.eclipse.swt.events.DisposeListener;
Eclipse RCP开发桌面程序
import  org.eclipse.swt.graphics.Rectangle;
Eclipse RCP开发桌面程序
import  org.eclipse.swt.opengl.GLData;
Eclipse RCP开发桌面程序
import  org.eclipse.swt.widgets.Composite;
Eclipse RCP开发桌面程序
import  org.eclipse.ui.part.ViewPart;
Eclipse RCP开发桌面程序
import  org.eclipse.swt.opengl.GLCanvas;
Eclipse RCP开发桌面程序
import  org.eclipse.swt.SWT;
Eclipse RCP开发桌面程序
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序
public   class  OpenGLView  extends  ViewPart  {
Eclipse RCP开发桌面程序
Eclipse RCP开发桌面程序    GLCanvas canvas;
Eclipse RCP开发桌面程序    @Override
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    
public void createPartControl(Composite parent) {
Eclipse RCP开发桌面程序        
// TODO 自动生成方法存根
Eclipse RCP开发桌面程序
        GLData data = new GLData();
Eclipse RCP开发桌面程序        data.depthSize 
= 1;
Eclipse RCP开发桌面程序        data.doubleBuffer 
= true;
Eclipse RCP开发桌面程序        canvas 
= new GLCanvas(parent, SWT.NO_BACKGROUND, data);
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        canvas.addControlListener(
new ControlAdapter() {
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序            
public void controlResized(ControlEvent e) {
Eclipse RCP开发桌面程序                Rectangle rect 
= canvas.getClientArea();
Eclipse RCP开发桌面程序                GL.glViewport(
00, rect.width, rect.height);
Eclipse RCP开发桌面程序                
Eclipse RCP开发桌面程序                
//选择投影矩阵
Eclipse RCP开发桌面程序
                GL.glMatrixMode(GL.GL_PROJECTION);
Eclipse RCP开发桌面程序                
//重置投影矩阵
Eclipse RCP开发桌面程序
                GL.glLoadIdentity();
Eclipse RCP开发桌面程序                
//设置窗口比例和透视图
Eclipse RCP开发桌面程序
                GLU.gluPerspective(45.0f, (float) rect.width / (float) rect.height, 0.1f100.0f);
Eclipse RCP开发桌面程序                
//选择模型观察矩阵
Eclipse RCP开发桌面程序
                GL.glMatrixMode(GL.GL_MODELVIEW);
Eclipse RCP开发桌面程序                
//重置模型观察矩阵
Eclipse RCP开发桌面程序
                GL.glLoadIdentity();
Eclipse RCP开发桌面程序                
Eclipse RCP开发桌面程序                
//黑色背景
Eclipse RCP开发桌面程序
                GL.glClearColor(0.0f0.0f0.0f0.0f);
Eclipse RCP开发桌面程序                
//设置深度缓存
Eclipse RCP开发桌面程序
                GL.glClearDepth(1.0f);
Eclipse RCP开发桌面程序                
//启动深度测试
Eclipse RCP开发桌面程序
                GL.glEnable(GL.GL_DEPTH_TEST);
Eclipse RCP开发桌面程序                
//选择深度测试类型
Eclipse RCP开发桌面程序
                GL.glDepthFunc(GL.GL_LESS);
Eclipse RCP开发桌面程序                
//启用阴影平滑
Eclipse RCP开发桌面程序
                GL.glShadeModel(GL.GL_SMOOTH);
Eclipse RCP开发桌面程序                
//精细修正透视图
Eclipse RCP开发桌面程序
                GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
Eclipse RCP开发桌面程序                
//清除屏幕和深度缓存
Eclipse RCP开发桌面程序
                GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
Eclipse RCP开发桌面程序                
//重置当前的模型观察矩阵
Eclipse RCP开发桌面程序
                GL.glLoadIdentity();
Eclipse RCP开发桌面程序            }

Eclipse RCP开发桌面程序        }
);  
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        canvas.addDisposeListener(
new DisposeListener() {
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序            
public void widgetDisposed(DisposeEvent e) {
Eclipse RCP开发桌面程序                dispose();
Eclipse RCP开发桌面程序            }

Eclipse RCP开发桌面程序        }
);
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        
/*
Eclipse RCP开发桌面程序        
Eclipse RCP开发桌面程序        
*/

Eclipse RCP开发桌面程序        
Eclipse RCP开发桌面程序        
Eclipse RCP开发桌面程序        Refresher rf 
= new Refresher(canvas);
Eclipse RCP开发桌面程序        rf.run();
Eclipse RCP开发桌面程序    }

Eclipse RCP开发桌面程序
Eclipse RCP开发桌面程序    @Override
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    
public void setFocus() {
Eclipse RCP开发桌面程序        
// TODO 自动生成方法存根
Eclipse RCP开发桌面程序

Eclipse RCP开发桌面程序    }

Eclipse RCP开发桌面程序
Eclipse RCP开发桌面程序}

Eclipse RCP开发桌面程序
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序
class  Refresher  implements  Runnable  {
Eclipse RCP开发桌面程序    
public static final int DELAY = 100;
Eclipse RCP开发桌面程序    
Eclipse RCP开发桌面程序    
private GLCanvas canvas;
Eclipse RCP开发桌面程序    
private float rotate = 0.0f;
Eclipse RCP开发桌面程序    
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    
public Refresher(GLCanvas canvas) {
Eclipse RCP开发桌面程序        
this.canvas = canvas;
Eclipse RCP开发桌面程序    }

Eclipse RCP开发桌面程序    
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序    
public void run() {
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        
if (this.canvas != null && !this.canvas.isDisposed()) {
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序            
if(!canvas.isCurrent()){
Eclipse RCP开发桌面程序                canvas.setCurrent();
Eclipse RCP开发桌面程序            }

Eclipse RCP开发桌面程序            
//这里添加OpenGL绘图代码
Eclipse RCP开发桌面程序
            GL.glLoadIdentity();
Eclipse RCP开发桌面程序            GL.glClear(GL.GL_COLOR_BUFFER_BIT 
| GL.GL_DEPTH_BUFFER_BIT);
Eclipse RCP开发桌面程序            GL.glTranslatef(
04.5f-11);
Eclipse RCP开发桌面程序            
//围绕y轴转起来
Eclipse RCP开发桌面程序
            rotate += 0.5;
Eclipse RCP开发桌面程序            GL.glRotatef(rotate, 
01.0f0);
Eclipse RCP开发桌面程序            
//调用递归函数,绘制三菱锥矩阵
Eclipse RCP开发桌面程序
            drawPyramid(0,0,0,4);
Eclipse RCP开发桌面程序            canvas.swapBuffers();
Eclipse RCP开发桌面程序            
this.canvas.getDisplay().timerExec(DELAY, this);
Eclipse RCP开发桌面程序        }

Eclipse RCP开发桌面程序    }

Eclipse RCP开发桌面程序        
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序        
public void drawPyramid(float x, float y, float z, int n){
Eclipse RCP开发桌面程序            
if(n == 0)return;
Eclipse RCP开发桌面程序            
//画一个三菱锥
Eclipse RCP开发桌面程序
            GL.glBegin(GL.GL_TRIANGLES);
Eclipse RCP开发桌面程序                
//画背面
Eclipse RCP开发桌面程序
                GL.glColor3f(1.0f,0.0f,0.0f);
Eclipse RCP开发桌面程序                GL.glVertex3f( x, y, z);
Eclipse RCP开发桌面程序                GL.glColor3f(
0.0f,1.0f,0.0f);
Eclipse RCP开发桌面程序                GL.glVertex3f(x
+1.0f,y-1.63f,z-0.57f);
Eclipse RCP开发桌面程序                GL.glColor3f(
0.0f,0.0f,1.0f);
Eclipse RCP开发桌面程序                GL.glVertex3f( x
-1.0f,y-1.63f,z-0.57f);
Eclipse RCP开发桌面程序                
//画底面
Eclipse RCP开发桌面程序
                GL.glColor3f(1.0f,0.0f,0.0f);
Eclipse RCP开发桌面程序                GL.glVertex3f( x,y
-1.63f,z+1.15f);
Eclipse RCP开发桌面程序                GL.glColor3f(
0.0f,1.0f,0.0f);
Eclipse RCP开发桌面程序                GL.glVertex3f(x
-1.0f,y-1.63f,z-0.57f);
Eclipse RCP开发桌面程序                GL.glColor3f(
0.0f,0.0f,1.0f);
Eclipse RCP开发桌面程序                GL.glVertex3f( x
+1.0f,y-1.63f,z-0.57f);
Eclipse RCP开发桌面程序                
//画左侧面
Eclipse RCP开发桌面程序
                GL.glColor3f(1.0f,0.0f,0.0f);
Eclipse RCP开发桌面程序                GL.glVertex3f( x,y,z);
Eclipse RCP开发桌面程序                GL.glColor3f(
0.0f,1.0f,0.0f);
Eclipse RCP开发桌面程序                GL.glVertex3f(x
-1.0f,y-1.63f,z-0.57f);
Eclipse RCP开发桌面程序                GL.glColor3f(
0.0f,0.0f,1.0f);
Eclipse RCP开发桌面程序                GL.glVertex3f( x,y
-1.63f,z+1.15f);
Eclipse RCP开发桌面程序                
//画右侧面
Eclipse RCP开发桌面程序
                GL.glColor3f(1.0f,0.0f,0.0f);
Eclipse RCP开发桌面程序                GL.glVertex3f( x,y,z);
Eclipse RCP开发桌面程序                GL.glColor3f(
0.0f,1.0f,0.0f);
Eclipse RCP开发桌面程序                GL.glVertex3f(x,y
-1.63f,z+1.15f);
Eclipse RCP开发桌面程序                GL.glColor3f(
0.0f,0.0f,1.0f);
Eclipse RCP开发桌面程序                GL.glVertex3f( x
+1.0f,y-1.63f,z-0.57f);
Eclipse RCP开发桌面程序            GL.glEnd();
Eclipse RCP开发桌面程序            
//递归调用,画多个三菱锥
Eclipse RCP开发桌面程序
            drawPyramid(x,y-1.63f,z+1.15f,n-1);
Eclipse RCP开发桌面程序            drawPyramid(x
-1.0f,y-1.63f,z-0.57f,n-1);
Eclipse RCP开发桌面程序            drawPyramid(x
+1.0f,y-1.63f,z-0.57f,n-1);
Eclipse RCP开发桌面程序        }

Eclipse RCP开发桌面程序}
Eclipse RCP开发桌面程序static  PIXELFORMATDESCRIPTOR pfd =       // pfd 告诉窗口我们所希望的东东
Eclipse RCP开发桌面程序Eclipse RCP开发桌面程序
      {
Eclipse RCP开发桌面程序         sizeof(PIXELFORMATDESCRIPTOR),   
//上诉格式描述符的大小
Eclipse RCP开发桌面程序
         1,                  // 版本号
Eclipse RCP开发桌面程序
         PFD_DRAW_TO_WINDOW |        // 格式必须支持窗口
Eclipse RCP开发桌面程序
         PFD_SUPPORT_OPENGL |        // 格式必须支持OpenGL
Eclipse RCP开发桌面程序
         PFD_DOUBLEBUFFER,          // 必须支持双缓冲
Eclipse RCP开发桌面程序
         PFD_TYPE_RGBA,           // 申请 RGBA 格式
Eclipse RCP开发桌面程序
         bits,                // 选定色彩深度
Eclipse RCP开发桌面程序
         000000,          // 忽略的色彩位
Eclipse RCP开发桌面程序
         0,                 // 无Alpha缓存
Eclipse RCP开发桌面程序
         0,                 // 忽略Shift Bit
Eclipse RCP开发桌面程序
         0,                 // 无聚集缓存
Eclipse RCP开发桌面程序
         0000,             // 忽略聚集位
Eclipse RCP开发桌面程序
         16,                 // 16位 Z-缓存 (深度缓存) 
Eclipse RCP开发桌面程序
         0,                 // 无模板缓存
Eclipse RCP开发桌面程序
         0,                 // 无辅助缓存
Eclipse RCP开发桌面程序
         PFD_MAIN_PLANE,           // 主绘图层
Eclipse RCP开发桌面程序
         0,                 // 保留
Eclipse RCP开发桌面程序
         000               // 忽略层遮罩
Eclipse RCP开发桌面程序
     }
;
Eclipse RCP开发桌面程序