java基础 ---SWT/JFace

java基础 ---SWT/JFace

很久没来博客写点东西了,主要是这段时间一直在研究SWT/JFace,在上周的总结我不是提到过吗,有机会会研究一下SWT和JFace。经过1个多星期的摸索,终于将之前用Swing设计的通讯录程序修改成使用SWT和JFace版本的了。说实话这个过程实在不是那么容易的,想必各位也知道在AWT和Swing这两大GUI界面API之外,还有个由IBM公司开发的一套专门用于设计GUI程序的API,这个就是SWT。即Standard widget Toolkit(标准窗口小部件工具)。不过到目前为止,SUN依然不接纳SWT/JFace作为java中的一种图形API标准,但是它依然借助Eclipse优异的表现,以不可阻挡之势发展着。用SWT设计出来的GUI程序是完全本地化的。也就是说它设计出的程序的外观会随着操作系统的变化而变化,不再象swing一样一成不变。高效性能也是SWT的优势之一,目前风靡全球的Eclipse就是基于SWT/JFace构建的,大家看看目前的Eclipse3.2就知道它有多棒了。在国内SWT/JFace这方面的资料也是比较少的,如果英文不错的话去eclipse的官方网站还是能找到很多的资料。我在使用SWT/JFace的时候主要参考了陈刚先生著作的<<Eclipse从入门到精通>>,这本书给了我很大的帮助,非常感谢该书的作者。还有就是eclipse的帮助文档,和官方网站,在这里也能找到非常多的资料。

关于SWT和JFace就不做过多的介绍了,如果有兴趣的话可以去http://blog.csdn.net/jayliu 这个博客看一下,这位前辈非常全面的介绍了SWT/JFace安装和使用。我这里主要是对在设计这个通讯录过程中的一些心得和体会做个总结。下面就以这个通讯录的设计作为主线贯穿全文,一步步的揭开SWT/JFace神秘的面纱。

在之前还是有必要说明一下SWT和JFace有什么区别,在写到这里之前,我都一直将SWT和JFace写在一起,也许让人感觉他们就是一回事。其实他们是有很大区别的,在最初只有SWT之套API的时候,设计出来的程序过于复杂,代码量很大,而且由于SWT所使用的一些API比较底层,不符合面向对象这个思路,Eclipse的开发小组又在SWT之上创建了一套更易用,功能更强大的图形包“JFace”,我们可以先看看官方是怎么定义这二者的区别的:“SWT 和 JFace 之间的界线是很明显的。SWT 根本不依赖于任何 JFace 或平台代码。JFace 用来在 SWT 库顶部提供常见的应用程序 UI 功能。JFace 并不试图“隐藏”SWT 或者替换它的功能。它提供一些类和接口,以处理与使用 SWT 来对动态 UI 编程相关联的许多常见任务。”我们可以这么来理解,JFace仅仅是作为对SWT的部分功能扩展,但不是全部,并且JFace并不会替代SWT中的任何功能,你可以完全不使用JFace而只使用SWT开发出任何你想要的程序。但是出于易用性等方面的考虑,一般在设计GUI的时候能用JFace的组件最好不用使用SWT的。只有当JFace不能满足我们的需要的时候才考虑使用SWT的组件,因此一般我们设计的SWT程序是SWT和JFace混合使用的,这也是为什么我会将SWT/JFace写到一起的原因。

下面分别是用Swing和SWT/JFace做出来程序,可以对比一下他们之间的差异。

Swing界面

SWT/JFace界面

1、建立主界面窗口
首先我们要做的就是建立一个主界面的窗口,这里我使用了JFace的ApplicationWindow窗口类,这个类继承JFace的Window类,在它上面可以加入菜单栏以及工具栏等等。首先看下这个建立窗口的大体框架。

public class MainFrame extends ApplicationWindow {

 
public MainFrame() {
  
//调用ApplicationWindow类的构造器,这行必须写出来,ApplicationWindow的默认构造器是需要shell参数
//的,我们可以将这个参数设置为null。
  super(null);
  
//加入菜单栏
  addMenuBar();

 }
 
//因为默认建立的菜单栏下面有一条水平线,JFace这里和SWT不同,SWT建立的菜单栏默认是没有水平线
//的。我们重写它的这个方法,去掉这个水平线。
 protected boolean showTopSeperator() {
   .
   .
   .
  
return false;
 }
 
//这个方法也是重在ApplicationWindow的方法,用来在窗口上加入部件的。象表格这类的组件也是要在这里
//加入的。
 protected Control createContents(Composite pare) {
   .
   .
   .
  
return pare;
 }
 
//这个方法是加入菜单栏,JFace是通过建立MenuManager,以及Action事件类来建立菜单栏,这个会在后面
//介绍。
 protected MenuManager createMenuManager() {
   .
   .
   .
  
return null;
 }
 
//下面是程序的主入口点,这个是jface建立窗口类必须要完成的一步,基本模式也就是这四句代码。
 public static void main(String [] args) {
  
//创建这个窗口类的对象
  MainFrame jface = new MainFrame();
  
//循环监听窗口的事件
  jface.setBlockOnOpen(true);
  
//建立窗口
  jface.open();
  
//当窗口关闭后要释放资源。
  Display.getDefault().dispose();
 }
}

建立一个JFace窗口基本框架就是这样,如果要加入工具栏就再添加一个
protected CoolBarManager createCoolBarManager(int style){}这个方法,将工具栏的代码写在这里面,然后在构造器里加入addToolBar(这里参数可以设置工具栏的一些样式);

直接运行上面程序后,会建立一个空白的窗口,是不是感觉确实不象用java设计出来的窗口。这个也是SWT特点之一。我们还可以设置一下窗口的标题以及大小等属性。

//获得窗口的shell对象
Shell shell = this.getShell();
Toolkit kit 
= Toolkit.getDefaultToolkit();
//设置窗口标题
shell.setText("我的通讯录-授权:Administrator");
//设置窗口默认大小
shell.setSize(700400);
//将窗口居中
shell.setLocation((kit.getScreenSize().width - 700/ 2, (kit.getScreenSize().height - 400/ 2);
//设置窗口最小的大小。这个设置主要是用来可以任意改变窗口大小,但又不想让窗口太小而使得窗口的组件
//变形。那么我们可以设置个最小的范围。
shell.setMinimumSize(700400);

将上段代码加入到createContents()方法里面就可以行了。
同样如果还想设置一下窗口的属性,比如建立模态窗口,或者建立个只有关闭按钮没有最大化按钮的窗口,可以在窗口类的构造器中加入:
this.setShellStyle(这里可以任意设置样式);能够设置的样式如下:(以下属性可以多选,但是某些属性相冲突时会导致设置的其他属性失效)
SWT.BORDER //建立一个有边框但没有标题栏的窗口
SWT.CLOSE //建立一个只有关闭按钮的窗口
SWT.MIN  //建立一个不能最大化的窗口
SWT.MAX, //建立一个可以最大化最小化的窗口
SWT.NO_TRIM //建立一个没有任何边界和标题栏的窗口
SWT.RESIZE //建立一个可以改变大小的窗口
SWT.TITLE //建立一个没有标题栏图标,没有关闭按钮的窗口
SWT.ON_TOP //建立一个总是在上的窗口,注意:此属性最好与CLOSE、MIN、MAX一起使用。
SWT.TOOL  //建立一个类似工具栏的窗口
SWT.APPLICATION_MODAL //建立一个APPLICATION模态窗口
SWT.MODELESS //建立一个非模态窗口
SWT.PRIMARY_MODAL //建立一个PRIMARY模态窗口
SWT.SYSTEM_MODAL  //建立一个SYSTEM模态窗口
还有两个快捷属性来建立窗口
SHELL_TRIM //建立一个标准模式的窗口,相当于属性设置为CLOSE | TITLE | MIN | MAX | RESIZE
DIALOG_TRIM //建立一个对话框模式的窗口,相当于属性设置为TITLE | CLOSE | BORDER
多选的时候只选中间使用|来分隔。

接下来介绍一下菜单栏的建立,使用JFace建立菜单不象SWT或者SWING那样来得那么直接。但是对处理菜单的事件就比较方面。比如说我们要在菜单栏、工具栏和弹出式菜单处理一个相同的事件,那么在SWT或者SWING中就需要写3份相同的代码,当然你也可以建立一个外部类来集中处理他们,但名称、图像以及一些其他的信息使用外部类就不太方便。JFace对以上问题提供了解决方案,JFace提供了一个Action类,它将名称、图像、动作处理程序都集中在其中,这样就可以共享这些Action来形成菜单项、工具栏按钮等。当然在最底层还是使用的MenuItem,将Action转化为MenuItem是由MenuManager来完成了。MenuManager简化了菜单的创建,一旦生成了MenuManager对象,就可以通用于菜单栏、弹出菜单、工具栏下拉菜单。下面我们简单建立一个菜单项,里面就三个选项:打开、保存和退出。并响应相应的事件。顺便这里再引入打开和保存对话框的使用。

首先我们要在主窗口的createMenuManager()方法中加入代码:

protected MenuManager createMenuManager() {
 
//建立一个相当于MenuBar的菜单管理器,以后建立的菜单都可以加入在这里面
 MenuManager menuBar = new MenuManager();
 
//建立第一个菜单项,相当于Swing里面的Menu,在字母的前面加上&符号就表示这项的快捷键是后面这个字
//母。
 MenuManager fileMenu = new MenuManager("文件(&F)");
 
//下面是为我们这个菜单加入子菜单项,相当于MenuItem
 fileMenu.add(new OpenFile());
 fileMenu.add(
new SaveFile());
 
//下面这句代码是插入一条水平线
 fileMenu.add(new Separator());
 fileMenu.add(
new Exit());
 
//将fileMenu这个菜单加入到menuBar里面。
 menuBar.add(fileMenu); 
 
//返回我们的menuBar这个菜单管理器,这句必须要有,否则就看不到菜单了。
 return menuBar;
 
}

下面我们就在这个类里面创建几个继承于action的类,这里我使用内部类的方式,当然也可以使用外部类。

private class OpenFile extends Action{
  
public OpenFile(){
  
//加上@ctrl+o就表示此菜单项的加速键是Ctrl+O,这样设置是不是很方便,记得在swing里面设置加速键还是
//比较麻烦的。
   setText("打开(&O)@Ctrl+O");
  }
  
public void run(){
   
//首先创建一个文件选择对话框FileDialog的对象,他的构造器的第一个参数是其父窗口的shell对象,SWT.
//OPEN表示此窗口是打开文件的窗口
   FileDialog fileDialog = new FileDialog(getShell(), SWT.OPEN);
   
//指定打开窗口时的默认路径。可以设置绝对和相对路径,这里设置的是当前文件所在的路径。
   fileDialog.setFilterPath("./");
   
//设置过滤文件的名字,里面参数是一个String数组,过滤的名字可以指定也可以不指定。比如我这里只指定
//了2个过滤文件的名字,最后一个exe文件的名字
并没有指定,但是当设置了文件类型后,默认把文件类型.exe作为此过滤文件的名字。
   fileDialog.setFilterNames(
new String[]{"所有文件(*.*)","Microsoft Excel(*.xls)"});
   
//设置过滤文件的类型,里面也是String数组。也就是说上面的名字怎么设置都无所谓,而真正过滤文件的是
//下面所指定的类型。
   fileDialog.setFilterExtensions(new String[]{"*.*","*.xls","*.exe"});
   
//最后需要使用open()方法来打开此对话框。当关闭对话框后会返回一个选择文件的绝对路径。如果点取消
//或者直接关闭对话框的话,会返回null。
   System.out.println(fileDialog.open());
  } 
 }
 
 
//保存文件对话框和打开文件对话框基本上一样,唯一不同的就是FileDialog构造器中第2个参数改为SWT.SA
//VE就表示该对话框是保存文件的对话框。
 
//怎么样是不是和windows的文件选择对话框一模一样。
 private class SaveFile extends Action{
  
public SaveFile(){
   setText(
"保存(&S)@Ctrl+S");
  }
  
public void run(){
   FileDialog fileDialog 
= new FileDialog(getShell(), SWT.SAVE);
   fileDialog.setFilterPath(
"./");
   fileDialog.setFilterNames(
new String[]{"所有文件(*.*)","Microsoft Excel(*.xls)"});
   fileDialog.setFilterExtensions(
new String[]{"*.*","*.xls","*.exe"});
   System.out.println(fileDialog.open());
  } 
 }
 
 
//最后是退出,获得主窗口的shell对象并使用dispose()方法将其释放掉,在程序的最后Display也会跟着被释
//放掉。
 private class Exit extends Action{
  
public Exit(){
   setText(
"退出(&X)@Ctrl+X");
  }
  
public void run(){
   getShell().dispose();
  } 
 }

 

上面建立这个菜单看起来好像比较烦琐,不过如果我们现在还想建立一个右键菜单,里面有两项,分别对应菜单的打开和保存这两个菜单项,这个时候JFace的方便之处就体现出来了,因为现在我们的窗口只暂时什么组件还没有,现在我要在空白的窗口中单击任何位置就能弹出下拉菜单,将下面几行代码加在主菜单的createContents()。

 //建立一个右键菜单的菜单管理器
 MenuManager popMenu = new MenuManager();
 
//复用我们刚才建立的OpenFile和SaveFile类
 popMenu.add(new OpenFile());
 popMenu.add(
new SaveFile());
 
//创建menu对象,因为当前窗口上什么都没有,所以pare这个Composite容器就可以接收我们的鼠标点击事
//件。当然如果想在其他组件或者容器上弹出菜单那么只需要将下面两句代码中的pare改成相应的组件就行。
 Menu menu = popMenu.createContextMenu(pare);
 
//将这个菜单加入到pare容器中。
 pare.setMenu(menu);

 

从上面我们可以看到,只要创建了Action对象,那么无论在工具栏还是菜单栏里面我们都可以复用它。这样就感觉方便多了。

时间很晚了,今天就暂时总结到这里,下回继续。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章