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對象,那麼無論在工具欄還是菜單欄裏面我們都可以複用它。這樣就感覺方便多了。

時間很晚了,今天就暫時總結到這裏,下回繼續。

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