RCP系统托盘实现方法

来源:互联网 发布:潮流计算软件 编辑:程序博客网 时间:2024/05/17 08:31
 

  1.                                         RCP系统托盘气泡提示和右键菜单的实现
  2.      实现系统托盘将程序最小化到Windows托盘,是一项有趣而且实用的工作。程序启动后自动最小化到Windows托盘。即使关闭程序,用户也可以随时通过托盘打开,非常方便快捷。
  3.     托盘对象简介实现系统托盘首先需要获得Windows托盘对象,托盘对象可以通过Display对象的getSystemTray()方法取得,代码如下:
  4. Tray tray = window.getShell().getDisplay().getSystemTray();
  5. 托盘对象的创建应该是在能够获得Display对象之后而程序窗口又没有打开之前,即ApplicationWorkbenchWindowAdvisor的postWindowOpen()方法中。
  6. 然后,向托盘对象中添加托盘项目TrayItem,并设置托盘项目的文字、图标。托盘项目及其图标应该在程序退出时销毁以释放资源。托盘项目创建方法如下:
  7. TrayItem trayItem = new TrayItem(tray, SWT.NONE);
  8. trayItem.setImage(trayImage);
  9. trayItem.setToolTipText("文字说明");
  10.     最后,需要添加托盘项目的事件监听处理,主要有两种,一种是用户单击托盘图标时需要打开程序,其监听事件为:
  11. trayItem.addListener(SWT.Selection, new Listener() {
  12.      public void handleEvent(Event event) {
  13.      //恢复程序界面
  14.      }
  15. });
  16. 另外一种是用户右键单击托盘图标时需要弹出菜单,其监听事件为:
  17. trayItem.addListener(SWT.MenuDetect, new Listener() {
  18.          public void handleEvent(Event event) {//处理代码}
  19.      });
  20. 最后还有一个问题,当用户关闭程序时不能关闭托盘图标。这需要复写Application- WorkbenchWindowAdvisor的preWindowShellClose()方法。
  21.   系统托盘的具体实现1.创建管理托盘的HookSysTray类,HookSysTray类实现托盘对象的创建和管理,其代码如下。
  22. cn.edu.jfcs.sys 
  23. import …
  24. public class HookSysTray {
  25.      private TrayItem trayItem;            //托盘项
  26.      private Image trayImage;                   //托盘图标
  27.      public HookSysTray() {}
  28.      public void createSysTray(final IWorkbenchWindow window) {
  29.          trayItem = initTrayItem(window); //初始化托盘
  30.          if (trayItem != null) {
  31.               trayPopupMenu(window);      //弹出托盘菜单项
  32.               trayMinimize(window);       //最小化窗口到托盘
  33.          }
  34.      }
  35.      // 用户单击窗口的最小化按钮时的处理
  36.      public void windowMinimized(final Shell shell) {
  37.          shell.setMinimized(true);            //最小化窗口
  38.          shell.setVisible(false);             //窗口不可见
  39.      }
  40.      // 最小化程序到托盘
  41.      private void trayMinimize(final IWorkbenchWindow window) {
  42.          window.getShell().addShellListener(new ShellAdapter() {
  43.               public void shellIconified(ShellEvent e) {
  44.                    window.getShell().setVisible(false);
  45.               }
  46.          });
  47.         
  48.  //用户单击托盘图标时使得主程序窗口可见并恢复为正常大小
  49.          trayItem.addListener(SWT.Selection, new Listener() {
  50.               public void handleEvent(Event event) {
  51.                    Shell shell = window.getShell();
  52.                    if (!shell.isVisible()) {
  53.                        shell.setVisible(true);
  54.                        window.getShell().setMinimized(false);
  55.                    }
  56.               }
  57.          });
  58.      }
  59.      // 托盘弹出菜单
  60.      private void trayPopupMenu(final IWorkbenchWindow window) {
  61.          trayItem.addListener(SWT.MenuDetect, new Listener() {
  62.               public void handleEvent(Event event) {
  63.                    MenuManager trayMenu = new MenuManager();  //创建菜单管理器
  64.                    //创建菜单
  65.                    Menu menu = trayMenu.createContextMenu(window.getShell());
  66.                    fillTrayItem(trayMenu, window);       //给托盘项目加上菜单
  67.                    menu.setVisible(true);               //菜单可见
  68.               }
  69.          });
  70.      }
  71.      // 构造托盘菜单项
  72.      private void fillTrayItem(IMenuManager trayItem,
  73.               final IWorkbenchWindow window) {
  74.          //创建退出系统菜单
  75.          Action exitSystem = new Action("退出系统[&E]", AbstractUIPlugin
  76.                    .imageDescriptorFromPlugin(IAppConstants.APPLICATION_ID,
  77.                             IImageKey.EXIT_SYSTEM)) {
  78.               public void run() {
  79.                    PlatformUI.getWorkbench().close();   //退出
  80.               }
  81.          };
  82.          trayItem.add(new Logoff());                    //创建用户注销菜单
  83.          trayItem.add(exitSystem);
  84.      }
  85.      // 初始化托盘项目的文字和图标
  86.      private TrayItem initTrayItem(IWorkbenchWindow window) {
  87.          //获得系统托盘
  88.          final Tray tray = window.getShell().getDisplay().getSystemTray();
  89.          if (tray == null)
  90.               return null;
  91.          trayItem = new TrayItem(tray, SWT.NONE);        //创建托盘项
  92.          trayImage = AbstractUIPlugin.imageDescriptorFromPlugin(
  93.                    IAppConstants.APPLICATION_ID, IImageKey .WINDOW_IMAGE)                 .createImage();                                    //创建托盘图像
  94.          trayItem.setImage(trayImage);                      //设置托盘图标
  95.          return trayItem;
  96.      }
  97.      public void Dispose() {
  98.          if (trayItem != null)   trayItem.dispose();         //释放托盘
  99.          if (trayImage != null)  trayImage.dispose();   //释放创建的图像资源
  100.      }
  101. }
  102. 程序说明:
  103.    程序向Windows托盘增加一个托盘图标和提示文字,并添加“用户注销”和“退出系统”两个托盘项。
  104.    MenuManager trayMenu = new MenuManager()是托盘的菜单管理器。
  105.    ExitSystem作为“退出系统”托盘项添加到托盘, PlatformUI.getWorkbench().close()用于关闭系统。
  106. l   trayItem.add(new Logoff())中的new Logoff()生成“用户注销”Action,并作为托盘项添加到托盘。
  107. 2.修改ApplicationWorkbenchWindowAdvisor类l   首先定义一个HookSysTray 对象:
  108. private HookSysTray hookSysTray;
  109.    添加用于创建hookSysTray对象的createSystemTray()方法:
  110. private void createSystemTray() {
  111.      hookSysTray = new HookSysTray();
  112.      hookSysTray.createSysTray(getWindowConfigurer().getWindow());
  113. }
  114.    修改postWindowOpen()方法,在该方法中调用createSystemTray()创建系统托盘:
  115. public void postWindowOpen() {
  116.      // 设置窗口自动居中
  117.      Shell shell = getWindowConfigurer().getWindow().getShell();
  118.      Rectangle screenSize = Display.getDefault().getClientArea();
  119.      Rectangle frameSize = shell.getBounds();
  120.      shell.setLocation((screenSize.width - frameSize.width) / 2,
  121.               (screenSize.height - frameSize.height) / 2);
  122.      createSystemTray();
  123. }
  124.    改写preWindowShellClose()方法,防止关闭程序时关闭托盘:
  125. public boolean preWindowShellClose() {
  126.      hookSysTray.windowMinimized(getWindowConfigurer().getWindow().getShell());
  127.      return false;
  128. }
  129.    退出时释放资源:
  130. public void dispose() {
  131.      hookSysTray.Dispose();
  132. }
  133.       图片的缓存处理创建图片是一项比较消耗系统资源的工作。众所周知,图片的使用原则是谁创建谁销毁以防止内存泄漏。系统使用图片的地方较多,因此应该统一高效地管理。将图片缓存起来,就可以在需要用到图片时直接从缓存中调用,而不是重新加载。下面是实现图片缓存处理的具体过程。
  134. 1.创建缓存CacheImage类CacheImage类负责创建、缓存、销毁图片等工作,以后凡是系统中需要使用图片的地方都由该类负责处理,代码如下。
  135. cn.edu.jfcs.sys / CacheImage.java
  136. import …
  137. public class CacheImage {
  138.      private final Map<String, Image> imageMap = new HashMap<String, Image>();
  139.      private static CacheImage INSTANCE=new CacheImage();
  140.      private CacheImage() {}
  141.      //采用单例模式,整个系统共用一个CacheImage唯一实例
  142.      public static CacheImage getINSTANCE(){
  143.          return INSTANCE;
  144.      } 
  145.      //获得图像
  146.      public Image getImage(String applicationID,String imageName) {
  147.          if (imageName == null)
  148.               return null;
  149.          Image image = (Image) imageMap.get(imageName);
  150.          if (image == null) {
  151.               image =AbstractUIPlugin.imageDescriptorFromPlugin(
  152.                        applicationID,imageName).createImage();
  153.               imageMap.put(imageName, image);//图像加入到Map中
  154.          }
  155.          return image;
  156.      }
  157.      //释放图像资源
  158.      public void dispose() {
  159.          //将Map对象转化成Iterator对象
  160.          Iterator iterator = imageMap.values().iterator();
  161.          while (iterator.hasNext())
  162.               ((Image) iterator.next()).dispose();  //释放iterator中的图像资源
  163.          imageMap.clear();                         //清除Map对象
  164.      }
  165. }
  166. 2.修改HookSysTray类
  167.    去掉private Image trayImage语句。
  168.    修改初始化托盘项目initTrayItem()方法:
  169. // 初始化托盘项目的文字和图标,代码中的黑体字部分为修改部分,下同。
  170. private TrayItem initTrayItem(IWorkbenchWindow window) {
  171.      final Tray tray = window.getShell().getDisplay().getSystemTray();
  172.      if (tray == null)   return null;
  173.      trayItem = new TrayItem(tray, SWT.NONE);
  174.      trayItem.setImage(CacheImage.getINSTANCE().getImage(
  175.               IAppConstants.APPLICATION_ID, IImageKey.WINDOW_IMAGE));
  176.      trayItem.setToolTipText(IAppConstants.APPLICATION_TITLE);
  177.      return trayItem;
  178. }
  179. 3.修改ApplicationWorkbenchWindowAdvisor类的dispose()方法public void dispose() {
  180.      hookSysTray.Dispose();
  181.      CacheImage.getINSTANCE().dispose();
  182. }
  183. 图像处理也可以采用图像描述符ImageDescriptor。ImageDescriptor的好处是不需要用户干预,由Java垃圾收集器自动释放和回收。前面创建Action时使用的就是图像描述符。当然,使用图像注册表ImageRegistry也是一个好方法,可以编写一个专门类利用图像注册表进行图像缓存管理。
  184.   定时自动显示托盘气泡提示文本气泡提示文本是一种非常友好的向用户展示信息的方式,很多软件的托盘图标都带有气泡提示文本,经常可见的气泡提示文本是向电脑插入U盘时显示的提示文本,其他还有瑞星杀毒软件、卡巴斯基、WindowsXP安全中心等等。Eclipse从3.2版本开始也支持气泡提示文本。
  185.     添加气泡提示文本其实非常简单,设置托盘项目trayItem的ToolTip就可以了。下面来实现一个能够每隔30分钟自动显示气泡提示文本的系统托盘,这需要修改初始化托盘项目文字和图标的initTrayItem()方法,黑体为新加代码。
  186. private TrayItem initTrayItem(final IWorkbenchWindow window) {
  187.      ……
  188.      trayItem.setImage(CacheImage.getINSTANCE().getImage(
  189.               IAppConstants.APPLICATION_ID, IImageKey.WINDOW_IMAGE));
  190.      // 定时显示气泡提示文本
  191.      Timer timer = new Timer();                      //创建定时器Timer
  192.      timer.schedule(new TimerTask() {
  193.          public void run() {
  194.               window.getShell().getDisplay().asyncExec(new Runnable() {
  195.                    public void run() {
  196.                        ToolTip tip = new ToolTip(window.getShell(),
  197.                                  SWT.BALLOON | SWT.ICON_INFORMATION);
  198.                        tip.setAutoHide(true); //自动隐藏气泡式提示文本
  199.                        //设置提示信息
  200.                        tip.setMessage(IAppConstants.APPLICATION_TITLE);
  201.                        tip.setText("欢迎使用");
  202.                        trayItem.setToolTip(tip);
  203.                        tip.setVisible(true);  //显示气泡式提示
  204.                    }
  205.               });
  206.          }
  207.      }, 0, 30 * 60 * 1000);
  208.      return trayItem;
  209. }
  210. 程序说明:
  211.    Timer是一个线程安全的定时器,这里设置的时间间隔为30分钟。为了调试程序时观察效果,可以设置得小一些,例如30秒(30×1000),调试好后再设置时间长些。
  212.    SWT.BALLOON设置提示文本为气泡式样,SWT.ICON_INFORMATION则表示带一个信息图标。
  213.    注意在Timer线程内部进行改变UI界面的操作时,需要使用window.getShell(). getDisplay().asyncExec()。