JFace是SWT的擴展.它提供了一組功能強大的界面組件.其中包含表格,樹,列表.對話框,向導對話框等.
表格是一種在軟件系統中很常用的數據表現形式.特別是基於數據庫的應用系統.表格更是不可缺少的界面組件.
SWT的表格組件(Table類)還是不怎么使用的,開發中一般還是使用JFace的表格組件TableViewer.
TableViewer是在SWT的Table類的基礎上擴展而來的.但是Table類並非TableViewer的父類.從下面的這兩個類的繼承圖就可以看出來
這兩個類甚至都不是同一個族系.
附上兩個類的繼承關系圖:
Table類的
和TableViewer的
從下面的TableViewer類源代碼可以看到,TableViewer把Table作為一個實例變量.
從而實現了對Table類的功能的擴展.

讓數據在TableViewer中顯示出來:
實體類的數據模型介紹:
以往的像ASP和PHP這類面向過程的編程模式,是從數據庫中讀取數據,也不用對數據做任何封裝,直接將數據一條條的顯示在表格中.
現在用Java這種面向對象的編程語言.我們應該用更規范的方式來操作數據.把數據庫中的記錄當做一個數據對象.
用一個類來表示.數據表的字段寫成類的實例變量,這樣的類在Java中叫做實體類.EJB的操作方式就是這樣的.Hibernate也是這樣.
數據庫和表格之間加上了實體類.這樣以往的"數據表→表格顯示"變成了"數據庫→實體類→表格顯示"這樣不是麻煩而是有很多好處:
1.表格顯示的代碼不再和數據庫相關.例如將數據庫由Oracle移植到MySQL時就不需要更改"數據庫→實體類"這個環節的代碼.
2.零散的字段變量統一在一個類中,程序代碼結構緊湊,清晰,有利於今后代碼段的維護,不要先看維護問題,很多系統做好后不敢再改,害怕改動后會牽扯到其他的地方,其中原因之一就是代碼的結構太亂,編程不規范所致.
3.將數據封裝在一個實體類中,在數據傳遞時也方便多了,可以將實體類作為一個參數在方法與方法之間來回傳遞.
數據在表格中的顯示
在得到由List裝載的包含數據信息的實體類對象后,接下來就是使用TableViewer來系那是這些數據,是吸納過程一般要經過如下步驟:
1.定義一個TableViewer的式樣,在定義之時,可以通過TableViewer構造函數提供的參數設置TableViewer的式樣,這和SWT中式樣的用法是一樣的.
2.將TableViewer置於容器類中,並對其布局.這和其他的SWT組件是一樣的.
3.創建TableViewer中的列(TableColumn)
4.用setInput方法輸入數據.setInput就像人的嘴巴.TableViewer的數據由setInput方法輸入.
5.設定內容器
6.設定標簽器.
這個地方出現了兩個新概念:內容器和標簽器.這是兩個重要的概念.在后面的JFace組件經常用到.
它們實際是IStructuredContentProvider,ITableLabelProvider這兩個接口的實現類.
它們的作用就是定義數據自Input進入后應該如何在TableViewer中顯示.因此這兩個類是非常關鍵的.
表格TableViewer表格類是JFace組件中重要且典型的一個組件,其中涉及了JFace中的眾多的重要的概念:內容器,便簽器,過濾器,排序器和修改器,這些概念對后面的JFace組件特別是TreeViewer的學習非常重要.之后也可以體會到JFace非常突出的面向對象的特性.
JFace是SWT的擴展,它提供了一組功能強大的界面組件,其中包含表格,樹,列表,對話框,向導對話框等.
表格是一種在軟件系統中很常見的數據表現形式,特別是基於數據庫的應用系統,表格更是不可缺少的界面組件,SWT的表格組件(Table類)前面已經介紹過了,但在實際項目開發中一般還是用JFace的表格組件TableViewer比較多,TableViewer組件是在SWT的Table組件基礎上采用MVC模式擴展而來的.但Table並非TableViewer的父類,
不和數據庫連接,自己建立一個實體類
People.java
1 /** 2 * 本類包含四個不同數據類型的變量,分別對應數據庫中的四個字段。 3 * 這些變量設置成private類型的,外界通過setter和getter方法訪問. 4 */ 5 public class People { 6 //這個地方id用的是包裝類型Long,最好不要用int,因為Long類型默認是null,int默認是0, 7 //方便區別數據庫中到底是0還是空. 8 private Long id; // 唯一識別碼,在數據庫里常為自動遞增的ID列 9 private String name; // 姓名 10 private boolean sex; //true是男,flase是女 11 private int age; // 年齡 12 private Date createDate; //這個地方Date聲明稱Long類型也可以.(1970年到現在的毫秒數) 13 14 public Long getId() { 15 return id; 16 } 17 public void setId(Long id) { 18 this.id = id; 19 } 20 public int getAge() { 21 return age; 22 } 23 public void setAge(int age) { 24 this.age = age; 25 } 26 public boolean isSex() { 27 return sex; 28 } 29 public void setSex(boolean sex) { 30 this.sex = sex; 31 } 32 public String getName() { 33 return name; 34 } 35 public void setName(String name) { 36 this.name = name; 37 } 38 public Date getCreateDate() { 39 return createDate; 40 } 41 public void setCreateDate(Date createDate) { 42 this.createDate = createDate; 43 } 44 }
數據的生成
由於數據操作是分兩步走:"數據庫---->實體類---->表格顯示",實體類隔離了代碼對數據庫的依賴,所以,"數據庫---->實體類"這一步就不講了,這部分的代碼於JFace組件的使用無關緊要,也不會影響表格組件的講解.關於數據庫方面,在后面的"插件項目實戰"中會 有詳細的示例.
由於沒有了"數據庫--->實體類"這一步了,那就實體類的對象如何生成呢?因為數據記錄和實體對象相對應,新創建的實體對象就相當於一個空記錄了,我們可以用其set方法一個個的將值投入實體對象中,這樣就能得到帶有數據的實體對象了.
為了今后便於擴展 ,將創建實體對象的方法集中在一個類中,這種專門負責創建對象的類又叫對象工廠.代碼如下.
生產People對象的PeopleFactory.java
1 public class PeopleFactory { 2 3 /** 4 * PeopleFactory這個類用於生成People類的對象. 5 * 在項目和應用中,這些個People類的對象都對應着數據庫中People表中的一條記錄. 6 * 手動封裝的People對象,放入到一個List集合中. 7 */ 8 public static List<People> getPeoples() { 9 //聲明一個list對象來放People類的對象 10 List<People> list = new ArrayList<People>(); 11 // 第1個實體類對象 12 People people1 = new People(); 13 people1.setId(new Long(1)); 14 people1.setName("張三"); 15 people1.setSex(true);//男 16 people1.setAge(28); 17 people1.setCreateDate(new Date()); // 當前日期 18 list.add(people1); 19 20 // 第2個實體類對象 21 People people2 = new People(); 22 people2.setId(new Long(2)); 23 people2.setName("李四"); 24 people2.setSex(false); 25 people2.setAge(18); 26 people2.setCreateDate(new Date()); 27 list.add(people2); 28 29 // 第3個實體類對象 30 People people3 = new People(); 31 people3.setId(new Long(3)); 32 people3.setName("王五"); 33 people3.setSex(true); 34 people3.setAge(27); 35 people3.setCreateDate(new Date()); 36 list.add(people3); 37 38 return list; 39 } 40 }
1.在實際應用中,getPeoples()方法的代碼可以從數據庫中取數據的代碼來替代.
2.這里的List不是SWT組件的List,而是Java基礎類中的java.util.List,它是屬於Java的集合類(Collection),List不是必須的,根據實際開發情況也可以用數組或其他集合來代替,如Set,Map等,Java一般都用集合Collection類存放數據.
數據在表格中的顯示.
在得到由List裝載的包含數據信息的實體類對象后,接下來就是使用TableViewer來顯示這些數據,實現過程一般需要經過如下步驟:
1.定義一個TableViewer對象.在定義的時候,可以通過TableViewer構造函數提供的參數設置TableViewer的式樣,這和SWT中式樣的用法是一樣的.
2.將TableViewer置於容器類中,並對其布局,這和其他的SWT組件是一樣的.
3.創建TableViewer中的列(TableColumn)
4.用setInput方法輸入數據,setInput就像人的嘴巴,TableViewer的數據由setInput方法輸入.
5.設定內容器
6.設定標簽器.
這里出現了兩個新概念:內容器,標簽器.這是兩個重要的概念,在后面的JFace組件中會經常用到.
他們實際是IStructuredContentProvider,ITableProvider這兩個接口的實現類.
它們的作用就是定義數據自Input進入后應該如何在TableViewer中顯示,因此這兩個類是很關鍵的.
整個的過程的流程圖如下:

一般來說,創建界面的代碼都是很長的,為了閱讀上的方便,可以將界面生成代碼分解成一個個的自定義的方法,同時將內容器和標簽器也各寫成一個單獨的類.
TableViewerContentProvider.java
1 /** 2 * 創建這個類,主要是對List集合中的數據記錄進行篩選和轉化. 3 * 是"內容器"的作用. 4 * 內容器中主要是對setInput()輸入的數據集集合(本例子中指的是在PeopleFactory中封裝好的List集合)做處理. 5 * 並且轉換化成一個數組返回. 6 * 7 * 實現對應的接口IStructuredContentProvider,然后實現其中的方法. 8 * @author kongxiaohan 9 */ 10 public class TableViewerContentProvider implements IStructuredContentProvider { 11 12 @Override 13 public void dispose() { 14 15 } 16 17 @Override 18 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { 19 20 } 21 22 //實現IStructuredContentProvider接口之后,主要復寫的就是這個getElements()方法. 23 @Override 24 public Object[] getElements(Object inputElement) {//setInput傳過來的是一個集合 25 if(inputElement instanceof List){//對這個參數進行類型的判斷. 26 return ((List)inputElement).toArray();//將setInput傳過來的List變成一個數組輸出 27 }else{ 28 return new Object[0]; 29 } 30 } 31 }
TableViewerLabelProvider.java
1 /** 2 * 這個方法主要是作為"標簽器"的作用來用的. 3 * "標簽器"將一個個實體對象的字段變量分別取出然后系那是在TableViewer的各個列中. 4 * 實現對應的接口 5 * @author kongxiaohan 6 */ 7 public class TableViewerLabelProvider implements ITableLabelProvider{ 8 @Override 9 public Image getColumnImage(Object element, int columnIndex) { 10 return null;//這個和getColumnText()不同的是,這個方法可以返回一個null值. 11 } 12 13 /** 14 * 由此方法決定數據記錄在表格的每一列是顯示什么文字 15 * @param element 實體類對象 16 * @param columnIndex 列號,0是第一列 17 * @return 返回值一定要避免NULL值,否則出錯 18 */ 19 @Override 20 public String getColumnText(Object element, int columnIndex) { 21 People people = (People) element; 22 if(columnIndex == 0){ 23 return people.getId().toString(); 24 } 25 26 if(columnIndex == 1){ 27 return people.getName(); 28 } 29 30 if(columnIndex == 2){ 31 return people.isSex() ? "男" : "女"; 32 } 33 34 if(columnIndex == 3){ 35 return people.getAge() + ""; 36 //這個地方是boolen類型的set和getter方法特別的地方.是"is"開頭的 37 } 38 39 if(columnIndex == 4){ 40 return people.getCreateDate().toString(); 41 } 42 //當都不符合的時候返回一個空字符串 43 return ""; 44 } 45 46 //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>書上說以下這幾個方法用處不大,空實現就可以了>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 47 @Override 48 public void addListener(ILabelProviderListener listener) { 49 50 } 51 52 @Override 53 public void dispose() { 54 55 } 56 57 @Override 58 public boolean isLabelProperty(Object element, String property) { 59 return false; 60 } 61 62 @Override 63 public void removeListener(ILabelProviderListener listener) { 64 65 } 66 }
右鍵菜單的MyActionGroup.java
1 //繼承ActionGroup 2 public class MyActionGroup extends ActionGroup{ 3 private TableViewer tableViewer; 4 5 /** 6 * 鼠標右鍵有菜單,首先要 7 * 生成菜單Menu,並將兩個Action傳入 8 */ 9 public void fillContextMenu(IMenuManager mgr){//I開頭的一般是接口的意思. 10 //加入兩個Action對象到菜單管理器中 11 MenuManager menuManager = (MenuManager) mgr; //因為傳入的是一個接口,所以這個地方要轉換一下類名. 12 menuManager.add(new OpenAction()); 13 menuManager.add(new RefreshAction()); 14 15 /* 16 * 這一段代碼是什么意思..........????????有點搞不懂. 17 */ 18 //生成Menu並掛載表格table上,menu和table兩個對象互為對方的參數. 19 Table table = tableViewer.getTable(); 20 Menu menu = menuManager.createContextMenu(table); 21 table.setMenu(menu); 22 23 } 24 25 /** 26 * 用來接受TableViewer對象的構造函數。 27 * 因為在Action會要使用到TableViewer對象 所以一定要把TableViewer傳進來。 28 */ 29 public MyActionGroup(TableViewer tableViewer) { 30 this.tableViewer = tableViewer; 31 } 32 33 /** 34 * "打開"的Action類 35 */ 36 private class OpenAction extends Action{ 37 public OpenAction(){ 38 setText("打開"); 39 } 40 /** 41 * 繼承自Action的方法,動作代碼寫在此方法中. 42 */ 43 public void run(){ 44 IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); 45 People obj = (People) (selection.getFirstElement()); 46 if (obj == null) { 47 MessageDialog.openInformation(null, null, "選選擇記錄"); 48 } else { 49 MessageDialog.openInformation(null, null, obj.getName()); 50 } 51 } 52 } 53 54 /** 55 * 刷新的Action類 56 */ 57 private final class RefreshAction extends Action{ 58 public RefreshAction(){ 59 setText("刷新"); 60 } 61 62 public void run(){ 63 tableViewer.refresh();//調用表格的刷新方法. 64 } 65 } 66 }
三個TableViewer的實體類
TableViewer1.java
1 /** 2 * TableViewer類的實現類 3 * @author kongxiaohan 4 */ 5 public class TableViewer1 { 6 //首先定義一個表格(TableViewer類)對象 7 private TableViewer tableviewer; 8 9 public static void main(String[] args) { 10 TableViewer1 window = new TableViewer1(); 11 window.open(); 12 } 13 14 //定義這個open()方法.就是創建一個典型的SWT程序的步驟 15 public void open(){ 16 //1.display負責管理一實現循環和控制UI線程和其他線程之間的通信 17 Display display = new Display(); 18 //2.創建一個或者多個Shell(shell是程序的主窗口) 19 Shell shell = new Shell(); 20 //3.設置shell的布局. 21 shell.setSize(500, 150); 22 //設置shell的布局為FillLayout 23 shell.setLayout(new FillLayout()); 24 shell.setText("TableViewer的第一個例子"); 25 //調用自定義的方法創建表格 26 createTableViewer(shell); 27 //4.設定內容器 28 tableviewer.setContentProvider(new TableViewerContentProvider()); 29 //5.設定標簽器 30 tableviewer.setLabelProvider(new TableViewerLabelProvider()); 31 //6.用setInput輸入數據(把PeopleFactory產生的List集合傳進來) 32 tableviewer.setInput(PeopleFactory.getPeoples()); 33 34 //7.創建Shell中的組件(這個例子中沒有加入組件,只有一個空窗口) 35 shell.open(); 36 //8.寫一個時間轉發循環 37 while(!shell.isDisposed()){//如果主窗口沒有關閉,則一直循環 38 //dispose 是"處理,處置,毀掉"的意思 39 if(!display.readAndDispatch()){//// 如果display不忙 40 display.sleep();// display休眠 41 } 42 } 43 } 44 45 46 /** 47 * 創建一個表格 48 */ 49 public void createTableViewer(Composite prarent){ 50 /** 51 * 第一步:定義一個TableViewer對象. 52 * 同時在構造方法中定義其式樣. 這里設置成可以多選(SWT.MULTI), 53 * 有水平滾動條(SWT.H_SCROLL),有垂直滾動條(SWT.V_SCROLL), 54 * 有邊框(SWT.BORDER),可以整行選擇(SWT.FULL_SELECTION) 55 */ 56 tableviewer = new TableViewer(prarent, SWT.MULTI | SWT.H_SCROLL 57 | SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.FULL_SELECTION ); 58 59 /** 60 * 第二步:通過TableViewer中的Table對其布局. 61 */ 62 Table table = tableviewer.getTable(); 63 table.setHeaderVisible(true);//設置標頭 64 table.setLinesVisible(true);//顯示表格線 65 TableLayout tLayout = new TableLayout();//專用於表格的布局 66 table.setLayout(tLayout); 67 68 /** 69 * 第三步:建立TableViewer中的列 70 */ 71 tLayout.addColumnData(new ColumnWeightData(20));//這個是設置ID列的列寬為10像素 72 new TableColumn(table, SWT.NONE).setText("ID號"); 73 74 tLayout.addColumnData(new ColumnWeightData(20));//這個是設置ID列的列寬為40像素 75 new TableColumn(table, SWT.NONE).setText("姓名"); 76 77 tLayout.addColumnData(new ColumnWeightData(20));//這個是設置ID列的列寬為10像素 78 new TableColumn(table, SWT.NONE).setText("性別"); 79 80 tLayout.addColumnData(new ColumnWeightData(20));//這個是設置ID列的列寬為10像素 81 new TableColumn(table, SWT.NONE).setText("年齡"); 82 83 tLayout.addColumnData(new ColumnWeightData(70));//這個是設置ID列的列寬為70像素 84 new TableColumn(table, SWT.NONE).setText("記錄建立時間"); 85 } 86 }
程序說明:
TableViewer的setInput方法的參數類型是Object,所以它可以接受任何類型的參數,SWT/JFace中很多參數都是這樣的,所以參數對象進入到方法內部后要機型類型和轉換,這是個比較麻煩的一件事,因此在內容器里要將參數轉換過來,如(List)element.但如果某種情況下element參數不是List類型,程序就會報錯,所以最好用element instanceof List來做一下類型判斷比較穩妥,在SWT/JFace編程中很多的BUG都出現在這種地方.
還有一個出BUG比較多的是空值(null)的判斷,實踐經驗表明,50%以上的BUG都出在空值異常上,像內容器的getColumnImage方法能返回null值,但getColumnText返回null值就會出錯,所以為了程序的穩定和健壯,對方法的參數做一下空值判斷是非常有必要的,除非你確定該值不可能為空值.
TableViewer.java的運行結果:

TableViewer2.java
1 /** 2 * 這個例子比TableViewer1多了一個雙擊一條記錄會彈出一個含有姓名的對話框 3 * 僅僅是多了一個這樣的事件. 4 * @author kongxiaohan 5 */ 6 public class TableViewer2 { 7 //首先定義一個表格(TableViewer類)對象 8 private TableViewer tableViewer; 9 10 public static void main(String[] args) { 11 TableViewer2 window = new TableViewer2(); 12 //因為這類和TableViewer1的代碼基本上是一樣的,我就原樣拷貝過TableViewer1的代碼來了 13 //但是這個地方應該改成TableViewer2的. 14 window.open(); 15 } 16 17 //定義這個open()方法.就是創建一個典型的SWT程序的步驟 18 public void open(){ 19 //1.display負責管理一實現循環和控制UI線程和其他線程之間的通信 20 Display display = new Display(); 21 //2.創建一個或者多個Shell(shell是程序的主窗口) 22 Shell shell = new Shell(); 23 //3.設置shell的布局. 24 shell.setSize(500, 150); 25 //設置shell的布局為FillLayout 26 shell.setLayout(new FillLayout()); 27 shell.setText("TableViewer的第二個例子"); 28 //調用自定義的方法創建表格 29 createTableViewer(shell); 30 //4.設定內容器 31 tableViewer.setContentProvider(new TableViewerContentProvider()); 32 //5.設定標簽器 33 tableViewer.setLabelProvider(new TableViewerLabelProvider()); 34 //6.用setInput輸入數據(把PeopleFactory產生的List集合傳進來) 35 tableViewer.setInput(PeopleFactory.getPeoples()); 36 37 //>>>>>>>>>>>>>>>>相比於TableViewer1.java中新增加的>>>>>>>>>>>>>>>>> 38 //增加一個監聽器 39 addListener(); 40 41 42 //7.創建Shell中的組件(這個例子中沒有加入組件,只有一個空窗口) 43 shell.open(); 44 //8.寫一個時間轉發循環 45 while(!shell.isDisposed()){//如果主窗口沒有關閉,則一直循環 46 //dispose 是"處理,處置,毀掉"的意思 47 if(!display.readAndDispatch()){//// 如果display不忙 48 display.sleep();// display休眠 49 } 50 } 51 } 52 53 54 /** 55 * 創建一個表格 56 */ 57 public void createTableViewer(Composite prarent){ 58 /** 59 * 第一步:定義一個TableViewer對象. 60 * 同時在構造方法中定義其式樣. 這里設置成可以多選(SWT.MULTI), 61 * 有水平滾動條(SWT.H_SCROLL),有垂直滾動條(SWT.V_SCROLL), 62 * 有邊框(SWT.BORDER),可以整行選擇(SWT.FULL_SELECTION) 63 */ 64 tableViewer = new TableViewer(prarent, SWT.MULTI | SWT.H_SCROLL 65 | SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.FULL_SELECTION ); 66 67 /** 68 * 第二步:通過TableViewer中的Table對其布局. 69 */ 70 Table table = tableViewer.getTable(); 71 table.setHeaderVisible(true);//設置標頭 72 table.setLinesVisible(true);//顯示表格線 73 TableLayout tLayout = new TableLayout();//專用於表格的布局 74 table.setLayout(tLayout); 75 76 /** 77 * 第三步:建立TableViewer中的列 78 */ 79 tLayout.addColumnData(new ColumnWeightData(20));//這個是設置ID列的列寬為10像素 80 new TableColumn(table, SWT.NONE).setText("ID號"); 81 82 tLayout.addColumnData(new ColumnWeightData(20));//這個是設置ID列的列寬為40像素 83 new TableColumn(table, SWT.NONE).setText("姓名"); 84 85 tLayout.addColumnData(new ColumnWeightData(20));//這個是設置ID列的列寬為10像素 86 new TableColumn(table, SWT.NONE).setText("性別"); 87 88 tLayout.addColumnData(new ColumnWeightData(20));//這個是設置ID列的列寬為10像素 89 new TableColumn(table, SWT.NONE).setText("年齡"); 90 91 tLayout.addColumnData(new ColumnWeightData(70));//這個是設置ID列的列寬為70像素 92 new TableColumn(table, SWT.NONE).setText("記錄建立時間"); 93 } 94 95 /** 96 * 新增加的監聽器 97 */ 98 public void addListener(){ 99 //TableViewer的雙擊事件的監聽 100 tableViewer.addDoubleClickListener(new IDoubleClickListener() {//IDoubleClickListener是一個接口 101 @Override 102 public void doubleClick(DoubleClickEvent event) { 103 IStructuredSelection selection = (IStructuredSelection) event.getSelection(); 104 //得到記錄的實體對象(要類型轉換) 105 People people = (People) selection.getFirstElement(); 106 //一個彈出提示框 107 MessageDialog.openInformation(null, "提示", people.getName()); 108 } 109 }); 110 111 /* 112 * tv的選擇事件(單擊)監聽 113 */ 114 tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { 115 @Override 116 public void selectionChanged(SelectionChangedEvent event) { 117 // 如果要定義單擊的事件的處理在這里寫代碼....... 118 } 119 }); 120 } 121 }
TableViewer2.java的運行結果.
相比TableViewer1.java 多了一個雙擊記錄彈出名字的功能.

TableView3.java
1 /** 2 * 這個例子在TableViewer2的基礎上增加了右鍵的菜單 3 * @author kongxiaohan 4 */ 5 public class TableViewer3 { 6 //首先定義一個表格(TableViewer類)對象 7 private TableViewer tableViewer; 8 9 public static void main(String[] args) { 10 TableViewer3 window = new TableViewer3(); 11 //因為這類和TableViewer1的代碼基本上是一樣的,我就原樣拷貝過TableViewer1的代碼來了 12 //但是這個地方應該改成TableViewer2的. 13 window.open(); 14 } 15 16 //定義這個open()方法.就是創建一個典型的SWT程序的步驟 17 public void open(){ 18 //1.display負責管理一實現循環和控制UI線程和其他線程之間的通信 19 Display display = new Display(); 20 //2.創建一個或者多個Shell(shell是程序的主窗口) 21 Shell shell = new Shell(); 22 //3.設置shell的布局. 23 shell.setSize(500, 150); 24 //設置shell的布局為FillLayout 25 shell.setLayout(new FillLayout()); 26 shell.setText("TableViewer的第三個例子"); 27 //調用自定義的方法創建表格 28 createTableViewer(shell); 29 //4.設定內容器 30 tableViewer.setContentProvider(new TableViewerContentProvider()); 31 //5.設定標簽器 32 tableViewer.setLabelProvider(new TableViewerLabelProvider()); 33 //6.用setInput輸入數據(把PeopleFactory產生的List集合傳進來) 34 tableViewer.setInput(PeopleFactory.getPeoples()); 35 36 //>>>>>>>>>>>>>>>>相比於TableViewer1.java中新增加的>>>>>>>>>>>>>>>>> 37 //增加一個監聽器 38 addListener(); 39 //>>>>>>>>>>>>>>>>相比於TableViewer2.java中新增加的>>>>>>>>>>>>>>>>> 40 //生成一個ActionGroup對象. 41 MyActionGroup actionGroup = new MyActionGroup(tableViewer); 42 // 調用fillContextMenu方法將按鈕注入到菜單對象中 43 actionGroup.fillContextMenu(new MenuManager()); 44 45 46 47 //7.創建Shell中的組件(這個例子中沒有加入組件,只有一個空窗口) 48 shell.open(); 49 //8.寫一個時間轉發循環 50 while(!shell.isDisposed()){//如果主窗口沒有關閉,則一直循環 51 //dispose 是"處理,處置,毀掉"的意思 52 if(!display.readAndDispatch()){//// 如果display不忙 53 display.sleep();// display休眠 54 } 55 } 56 } 57 58 59 /** 60 * 創建一個表格 61 */ 62 public void createTableViewer(Composite prarent){ 63 /** 64 * 第一步:定義一個TableViewer對象. 65 * 同時在構造方法中定義其式樣. 這里設置成可以多選(SWT.MULTI), 66 * 有水平滾動條(SWT.H_SCROLL),有垂直滾動條(SWT.V_SCROLL), 67 * 有邊框(SWT.BORDER),可以整行選擇(SWT.FULL_SELECTION) 68 */ 69 tableViewer = new TableViewer(prarent, SWT.MULTI | SWT.H_SCROLL 70 | SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.FULL_SELECTION ); 71 72 /** 73 * 第二步:通過TableViewer中的Table對其布局. 74 */ 75 Table table = tableViewer.getTable(); 76 table.setHeaderVisible(true);//設置標頭 77 table.setLinesVisible(true);//顯示表格線 78 TableLayout tLayout = new TableLayout();//專用於表格的布局 79 table.setLayout(tLayout); 80 81 /** 82 * 第三步:建立TableViewer中的列 83 */ 84 tLayout.addColumnData(new ColumnWeightData(20));//這個是設置ID列的列寬為10像素 85 new TableColumn(table, SWT.NONE).setText("ID號"); 86 87 tLayout.addColumnData(new ColumnWeightData(20));//這個是設置ID列的列寬為40像素 88 new TableColumn(table, SWT.NONE).setText("姓名"); 89 90 tLayout.addColumnData(new ColumnWeightData(20));//這個是設置ID列的列寬為10像素 91 new TableColumn(table, SWT.NONE).setText("性別"); 92 93 tLayout.addColumnData(new ColumnWeightData(20));//這個是設置ID列的列寬為10像素 94 new TableColumn(table, SWT.NONE).setText("年齡"); 95 96 tLayout.addColumnData(new ColumnWeightData(70));//這個是設置ID列的列寬為70像素 97 new TableColumn(table, SWT.NONE).setText("記錄建立時間"); 98 } 99 100 /** 101 * 新增加的監聽器 102 */ 103 public void addListener(){ 104 //TableViewer的雙擊事件的監聽 105 tableViewer.addDoubleClickListener(new IDoubleClickListener() {//IDoubleClickListener是一個接口 106 @Override 107 public void doubleClick(DoubleClickEvent event) { 108 IStructuredSelection selection = (IStructuredSelection) event.getSelection(); 109 //得到記錄的實體對象(要類型轉換) 110 People people = (People) selection.getFirstElement(); 111 //一個彈出提示框 112 MessageDialog.openInformation(null, "提示", people.getName()); 113 } 114 }); 115 116 /* 117 * tv的選擇事件(單擊)監聽 118 */ 119 tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { 120 @Override 121 public void selectionChanged(SelectionChangedEvent event) { 122 // 如果要定義單擊的事件的處理在這里寫代碼....... 123 } 124 }); 125 } 126 }
TableViewer3.java的運行結果是:
相比TableViewer2.java 多了一個右鍵菜單的功能.

