熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

用JFace和SWT構建簡單的應用程序

2013-11-23 20:38:29  來源: Java開源技術 

  簡介
  開放源碼 Eclipse 項目是 Java 領域中最有趣的新近開發項目之一Eclipse 把自己描述成一種通用的工具平台 — 開放的可擴展 IDE可用於任何用途且沒有特殊之處它的兩個主要組件是名為 SWT 的圖形庫和與其匹配的名為 JFace 的實用程序框架
  
  SWT 是一個窗口構件集和圖形庫它集成於本機窗口系統但有獨立於 OS 的 API
  
  JFace 是用 SWT 實現的 UI 工具箱它簡化了常見的 UI 編程任務JFace 在其 API 和實現方面都是獨立於窗口系統的它旨在使用 SWT 而不隱藏它 演示了 EclipseJFace 和 SWT 之間的關系
  
 

  
Eclipse WorkbenchJFace 和 SWT

  
  Hello World
  
  讓我們從我能想到的最簡單的 JFace 程序開始逐步擴充它將其構建為最常見的Hello World程序
  
  清單 Hello(版本
  
  import orgeclipsejfacewindow*;
  import orgeclipseswtwidgets*;
  public class Hello
  {
  public static void main(String[] args)
  {
  ApplicationWindow w = new ApplicationWindow(null);
  wsetBlockOnOpen(true);
  wopen();
  DisplaygetCurrent()dispose();
  }
  }
  
  這裡我們創建了一個名為 Hello 的類其中 main 方法僅僅創建了一個 ApplicationWindow然後打開它setBlockOnOpen() 使 open() 阻塞直到窗口關閉為止在窗口已關閉之後我們獲取當前的 Display 並除去它這會釋放在操作系統中用到的資源當您運行該程序時您會看到類似圖 的窗口
  
 

  
Hello(版本

  
  就是如此它甚至沒有說Hello World在修正它之前讓我們把話題轉到 JFace 窗口
  
  JFace 應用程序窗口
  窗口是頂級窗口(換句話說由 OS 窗口管理器管理的窗口)的 JFace 類JFace 窗口實際上不是頂級窗口的 GUI 對象(SWT 已經提供了一個名為 Shell)相反JFace 窗口是助手對象它知道對應的 SWT Shell 對象並提供代碼來幫助創建/編輯它以及偵聽它的事件等 演示了您的代碼JFace 和 SWT 之間的關系
  
 

  
您的代碼JFace Window 和 SWT Shell 之間的關系

  
  事實上這一模型是理解 JFace 如何工作的關鍵它並不真的是 SWT 之上的層而且它沒有試圖向您隱藏 SWT相反JFace 意識到有幾種使用 SWT 的常用模式而且它提供了一些實用程序代碼以幫助您更方便地對這些模式編程為了做到這一點JFace 提供可使用的對象或提供可將其子類化的類(有時它兩者都提供)
  
  盡管我們僅僅直接使用了一個 ApplicationWindow但實際上它們被設計為可以子類化也可以加入特定行為它們有現成的菜單欄工具欄供您插入特定於應用程序的內容的區域和狀態欄 — 全都是可選的 用 JFace File Explorer 示例本身演示了這些區域
  
 

  
應用程序窗口的各個部分

  
  讓我們改進 Hello使它成為 ApplicationWindow 的子類更改的行在清單 中突出顯示
  
  清單 Hello(版本
  
  import orgeclipsejfacewindow*;
  import orgeclipseswtwidgets*;
  public class Hello extends ApplicationWindow
  {
  public Hello()
  {
  super(null);
  }
  public static void main(String[] args)
  {
  Hello w = new Hello();
  wsetBlockOnOpen(true);
  wopen();
  DisplaygetCurrent()dispose();
  }
  }
  
  您編寫的構造函數必須調用超類構造函數(如往常一樣)讓我們暫時不考慮該構造函數的參數運行該程序的結果與前一個程序沒有任何不同缺省情況下程序不會為我們顯示任何裝飾性的東西我們的程序要創建一個帶有文本Hello World的按鈕這個按鈕要顯示在內容(Contents)區域要做到這一點我們必須實現 Control createContents(Composite parent) 方法
  
  ApplicationWindow 將在所有其它窗口構件已經創建之後但窗口在屏幕上顯示之前調用該方法參數 parent 是代表內容區域的復合窗口構件這裡的想法是您創建一個復合窗口構件將其添加到 parent然後添加您的窗口構件並返回您創建的復合窗口構件 演示了實例層次結構
  
 

  
Application Window 的實例層次結構

  
  我們的內容目前非常簡單parent 下的單一按鈕如清單 所示
  
  清單 Hello(版本
  
  import orgeclipsejfacewindow*;
  import orgeclipseswt*;
  import orgeclipseswtwidgets*;
  public class Hello extends ApplicationWindow
  {
  public Hello()
  {
  super(null);
  }
  protected Control createContents(Composite parent)
  {
  Button b = new Button(parent SWTPUSH);
  bsetText(Hello World);
  return b;
  }
  public static void main(String[] args)
  {
  Hello w = new Hello();
  wsetBlockOnOpen(true);
  wopen();
  DisplaygetCurrent()dispose();
  }
  }
  
  結果是圖
  
 

  
Hello(版本

  
  這就是我們要實現的我們使用 JFace 創建的第一個Hello World程序包含單一按鈕的窗口現在讓我們繼續討論文件資源管理器這一話題首先我們將創建顯示文件夾層次結構的樹查看器使用 TreeViewer 和 ApplicationWindow 一樣TreeViewer 不是真正的 SWT 窗口構件它也沒有打算向您隱藏 SWT 窗口構件它使用 SWT 樹窗口構件來顯示各項並且還使用許多其它對象來協助它不象 ApplicationWindowJFace TreeViewer 並不旨在被子類化
  
  這裡的想法是 TreeViewer 知道要顯示的樹的根元素當然您必須告訴它那個對象是什麼TreeViewer: void setInput(Object rootElement)
  
  為了開始顯示樹查看器向根元素請求子元素並顯示它們然後當用戶展開其中的一個子元素時樹查看器向該節點請求子元素以此類推實際上並不完全是那樣TreeViewer 並不直接使用域對象 — 而是使用另一個名為 ContentProvider 的對象這個對象才使用域對象如圖 所示
  

  
TreeViewerContentProvider 和域對象

  當然您必須實現 ContentProvider對於 TreeViewer您的類必須實現 ITreeContentProvider 接口實現 TreeContentProvider
  
  有六個方法需要實現實際上我們不用做全部的工作只需實現其中的三個就行因此本著即時滿意(instant gratification)的精神讓我們暫時只考慮那幾個方法吧下面的代碼演示了樹查看器如何向內容提供程序請求正好位於根元素下的頂級元素
  
  ITreeContentProvider: public Object[] getElements(Object element)
  

  隨後每當它需要特定元素的子元素時它就使用以下方法
  
  ITreeContentProvider: public Object[] getChildren(Object element)
  
  為了知道某個節點是否有子元素(有的話會將小加號放到它旁邊)樹查看器只需請求該節點的子元素然後會詢問有多少子元素萬一您的代碼需要更快捷的方法來做到這一點則您必須實現另一個方法
  
  public boolean hasChildren(Object element)
  
  正如您所見內容提供程序不持有對任何域對象的引用持有對這些域對象的引用的是樹查看器本身它把這些域對象作為參數傳遞給內容提供程序中的各個方法在我們的例子中節點是 File 對象為獲取子元素我們使用 listFiles()我們必須記得要檢查 listFiles() 是否返回 null然後使其變成空數組為了獲取頂級元素(正好位於根元素之下)我們只需重用 getChildren() 方法
  
  getParent() 方法被用來實現 reveal(Object element) 方法後者使樹查看器滾動其 SWT 樹窗口構件以便顯示樹中特定的節點問題是如果此刻實際上並沒有顯示那個節點那麼應該在哪裡顯示它?JFace 會尋找其父元素以及父元素的父元素等等直到它達到已顯示的節點然後它再次回頭尋找直到目標節點已顯示
  
  hasChildren() 方法只是做了顯而易見(未優化)的事情最後我們有了清單 中所示的代碼
  
  清單 FileTreeContentProvider(版本
  
  import javaio*;
  import javautil*;
  import orgeclipsejfaceviewers*;
  public class FileTreeContentProvider implements ITreeContentProvider
  {
  public Object[] getChildren(Object element)
  {
  Ob

  實現頂級 Explorer 類
  我們將采用 Hello World 程序更改其名稱然後用 createContents() 方法創建 TreeViewer(而不是創建一個按鈕)將其內容提供程序設置為我們的文件樹內容提供程序然後將輸入設置到某個文件夾在這個例子中我選擇的文件夾是 C: 驅動器中的頂級文件夾
  
  注需要從 createContents() 返回 SWT 窗口構件正如前面提到的JFace Tree Viewer 不是 SWT 窗口構件因此我們不能將它返回我們需要從樹查看器獲取真正的窗口構件我們通過使用 getTree() 做到這一點我們的主窗口類現在看起來與下面相似
  
  清單 Explorer(版本
  
  import javaio*;
  import orgeclipsejfaceviewers*;
  import orgeclipsejfacewindow*;
  import orgeclipseswt*;
  import orgeclipseswtwidgets*;
  public class Explorer extends ApplicationWindow
  {
  public Explorer()
  {
  super(null);
  }
  protected Control createContents(Composite parent)
  {
  TreeViewer tv = new TreeViewer(parent);
  tvsetContentProvider(new FileTreeContentProvider());
  tvsetInput(new File(C:\\));
  return tvgetTree();
  }
  public static void main(String[] args)
  {
  Explorer w = new Explorer();
  wsetBlockOnOpen(true);
  wopen();
  DisplaygetCurrent()dispose();
  }
  }
  
  運行該程序您將看到與圖 相似的結果
  

 

  

Explorer(版本

  除了樣板文件代碼我們只需向 Hello World 程序添加 行代碼就可做到這一點正如您可能猜想的那樣程序用 File 的 toString() 方法來顯示這些文件這不是我們真正想要的要改變這一點我們需要提供一個標簽提供程序
  
  實現標簽提供程序
  正如有一個內容提供程序對象可用來獲取樹節點的子元素一樣當需要實際顯示這些節點時樹查看器有另一個助手對象標簽提供程序和前面一樣我們需要設置它
  
  public void setLabelProvider(IBaseLabelProvider labelProvider)
  
  而且需要實現下面的方法以返回要為每個元素顯示的文本
  
  public String getText(Object element)
  
  如果我們將標簽提供程序添加到樹查看器圖中就會得到圖
  

 

  

顯示內容提供程序和標簽提供程序的樹查看器

  我們可以實現接口 ILabelProvider但將缺省實現 LabelProvider 子類化更容易(如果沒有顯式地設置標簽提供程序則使用的就是這個類)我們希望利用 getText() 做的事是返回文件名最後的部分 — 相對文件名而非 toString() 缺省使用的絕對文件名 演示了代碼
  
  圖 FileTreeLabelProvider(版本
  
  import javaio*;
  import orgeclipsejfaceviewers*;
  public class FileTreeLabelProvider extends LabelProvider
  {
  public String getText(Object element)
  {
  return ((File) element)getName();
  }
  }
  
  而且我們必須記得使樹查看器使用這個標簽提供程序如清單 所示
  
  清單 Explorer(版本
  
  import javaio*;
  import orgeclipsejfaceviewers*;
  import orgeclipsejfacewindow*;
  import orgeclipseswt*;
  import orgeclipseswtwidgets*;
  public class Explorer extends ApplicationWindow
  {
  public Explorer()
  {
  super(null);
  }
  protected Control createContents(Composite parent)
  {
  TreeViewer tv = new TreeViewer(parent);
  tvsetContentProvider(new FileTreeContentProvider());
  tvsetLabelProvider(new FileTreeLabelProvider());
  tvsetInput(new File(C:\\));
  return tvgetTree();
  }
  public static void main(String[] args)
  {
  Explorer w = new Explorer();
  wsetBlockOnOpen(true);
  wopen();
  DisplaygetCurrent()dispose();
  }
  }
  
  這一次運行該程序時我們會獲得更清楚的視覺效果如圖 所示
  

 

  

Explorer(版本

  我們現在要做的是將樹查看器移到左邊將一個表查看器放在右邊以顯示在樹查看器中已選中的文件夾中的文件列表
  
  使用表查看器
  為了處理表JFace 有一個 TableViewer和 TreeViewer 一樣它有輸入(根對象)內容提供程序和標簽提供程序它比樹查看器簡單因為它不需要處理樹 演示了內容提供程序和標簽提供程序
  

 

  

顯示內容提供程序和標簽提供程序的表查看器

  設置輸入對象的方法與前面相同
  
  TableViewer: void setInput(Object rootElement)
  

  實現文件表查看器內容提供程序
  讓我們考慮內容提供程序這一次根元素比樹查看器根元素簡單表查看器僅僅期望根對象有許多子元素因此要實現的唯一有趣方法是獲取子元素的方法
  
  public Object[] getElements(Object rootElement)
  
  要實現的接口是 IStructuredContentProvider
  
  根對象是一個文件夾其子元素是該文件夾包含的文件/文件夾因此我們的文件表內容提供程序類與清單 類似
  
  清單 FileTableContentProvider(版本
  
  import javaio*;
  import orgeclipsejfaceviewers*;
  public class FileTableContentProvider implements IStructuredContentProvider
  {
  public Object[] getElements(Object element)
  {
  Object[] kids = null;
  kids = ((File) element)listFiles();
  return kids == null ? new Object[] : kids;
  }
  public void dispose()
  {
  }
  public void inputChanged(Viewer viewer Object old_object Object new_object)
  {
  }
  }
  
  因此我們現在有兩個查看器樹查看器和表查看器為了將它們相鄰地安置在一起我們創建了 SWT SashForm 窗口構件該窗口構件用一個用戶可以調節的邊框分隔其子元素然後我們將樹和表添加到框格表單(sash form)(圖
  

 

  

包含樹查看器和表查看器的框格表單

  接下來要做的是使表查看器查看用戶在樹查看器中選中的每個文件夾要做到這一點我們必須偵聽事件
  
  偵聽事件
  當用戶在樹查看器中選中一項時樹查看器發出 SelectionChangedEvent 事件我們需要偵聽該事件當發出該事件時需要將表的輸入設置為樹查看器中當前選中的文件為了偵聽來自樹查看器的選擇更改事件我們使用下面的方法
  
  public void addSelectionChangedListener
  (ISelectionChangedListener listener)
  
  當用戶選中/取消選中樹查看器中的節點時用下面的方法調用選擇更改偵聽器
  
  public void selectionChanged(SelectionChangedEvent event)
  
  為了實現該偵聽器類我們將在主資源管理器窗口中編碼一個匿名類在 selectionChanged() 方法中我們將需要獲得剛選中的對象並使其成為表查看器的輸入將所有的工作組合在一起就得到了清單
  
  清單 Explorer(版本
  
  import javaio*;
  import orgeclipsejfaceviewers*;
  import orgeclipsejfacewindow*;
  import orgeclipseswt*;
  import orgeclipseswtcustom*;
  import orgeclipseswtwidgets*;
  public class Explorer extends ApplicationWindow
  {
  public Explorer()
  {
  super(null);
  }
  protected Control createContents(Composite parent)
  {
  SashForm sash_form = new SashForm(parent SWTHORIZONTAL | SWTNULL);
  TreeViewer tv = new TreeViewer(sash_form);
  tvsetContentProvider(new FileTreeContentProvider());
  tvsetLabelProvider(new FileTreeLabelProvider());
  tvsetInput(new File(C:\\));
  final TableViewer tbv = new TableViewer(sash_form SWTBORDER);
  tbvsetContentProvider(new FileTableContentProvider());
  tvaddSelectionChangedListener(new ISelectionChangedListener()
  {
  public void selectionChanged(SelectionChangedEvent event)
  {
  IStructuredSelection selection =
  (IStructuredSelection) eventgetSelection();


From:http://tw.wingwit.com/Article/program/Java/ky/201311/28818.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.