Hướng dẫn sử dụng Eclipse JFace
Công ty Vĩnh Cửu tuyển dụng lập trình viên Java

1- Giới thiệu

Hãy đảm bảo rằng bạn đã có khái niệm về SWT, bạn cần làm một Project SWT trước khi bắt đầu với JFace. Bạn có thể xem hướng dẫn SWT tại:

2- JFace là gì?

Eclipse JFace là một API dựa trên SWT. JFace cung cấp các class và nền tảng để đơn giản hóa việc sử dụng SWT. JFace không làm ẩn đi API SWT. Do đó, kiến thức SWT vẫn là cơ bản và cần thiết.

JFace giúp đơn giản hóa:
  1. Đơn giản hóa việc giữa mô hình dữ liệu và hiển thị truực quan. Ví dụ như dữ liệu và hiển thị trên Table, ComboBox, Tree.
  2. JFace cũng cung cấp các lớp helper để quản lý hiệu quả tài nguyên hệ thống của bạn, giống như màu sắc, hình ảnh và phông chữ.
  3. JFace hỗ trợ điều khiển các Preference pages, wizard và các Dialog. Nó cũng cung cấp các tính năng hỗ trợ biểu tượng trang trí (icon decoration), và các trợ giúp đầu vào người dùng (user-input) cho các SWT control.
JFace được sử dụng trong các ứng dụng Desktop và hoàn toàn sử dụng tốt trong ứng dụng RAP. Trong tài liệu này các Demo được hướng dẫn trên ứng dụng Desktop.

3- Các thành phần JFace

4- Tạo Project

Chúng ta cũng tạo một Project giống như đã tạo một Project trong tài liệu hướng dẫn sử dụng SWT.
  • File/New/Project
  • Project name: JFaceTutorial
Project này sẽ chạy trên Desktop, bạn lựa chọn như hình minh họa dưới đây:
Nhập vào:
  • Package name: org.o7planning.tutorial.jface
Project được tạo ra.
Bạn cần khai báo một vài Bundle đòi hỏi, cụ thể là các OSGi SWT JFace.Chúng là các thư viện SWT & JFace.
Thêm vào Bundle:
  • org.eclipse.swt
Tiếp tục thêm các Bundle:
  • org.eclipse.jface
  • org.eclipse.jface.text
Chỉ khi bạn thêm vào 2 Bundle JFace nói trên vào Project, trên màn hình thiết kế của WindowBuilder sau này mới xuất hiện các thành phần JFace để kéo thả.
OK, giờ chúng ta bắt đầu với JFace.

5- Quản lý Resource

Tạo package:
  • org.o7planning.tutorial.jface.image
Và copy một vài file ảnh vào.
  • check.png:
Chúng ta sẽ xem cách SWT quản lý nguồn dữ liệu (Image, Color, Font) như thế nào, và JFace quản lý thế nào.
  • File/New/Other...
Nhập vào:
  • Package: org.o7planning.tutorial.jface.rs
  • Name: ResourceDemo

5.1- Cách SWT Quản lý Resource

Trước hết hãy xem cách SWT quản lý Resource như thế nào.
Một class SWTResourceManager tự động được sinh ra. Nó là một class có các method tiện tích để quản lý Image, Font, Color.
Tiếp tục đổi mầu chữ của Button:
Xem đoạn code được tạo ra trong class ResourceDemo.
/**
* Create contents of the window.
*/
protected void createContents() {
   shlResourceDemo = new Shell();
   shlResourceDemo.setSize(336, 249);
   shlResourceDemo.setText("Resource Demo");
   shlResourceDemo.setLayout(new RowLayout(SWT.HORIZONTAL));
   
   Button btnButtonU = new Button(shlResourceDemo, SWT.NONE);
   btnButtonU.setFont(SWTResourceManager.getFont("Arial", 12, SWT.NORMAL));
   btnButtonU.setForeground(SWTResourceManager.getColor(SWT.COLOR_BLUE));
   btnButtonU.setImage(SWTResourceManager.getImage(ResourceDemo.class, "/org/o7planning/tutorial/jface/image/check.png"));
   btnButtonU.setText("Button using SWT Resource Manager");
}

5.2- Cách JFace quản lý Resource

Và giờ là cách JFace quản lý Resource.
import org.eclipse.jface.resource.FontDescriptor;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;


// Tạo đối tượng quản lý Resource.
LocalResourceManager jfaceRsManager = new LocalResourceManager(
       JFaceResources.getResources(), shlResourceDemo);


Color color = jfaceRsManager.createColor(new RGB(200, 100, 0));
Font font = jfaceRsManager.createFont(FontDescriptor.createFrom(
       "Arial", 10, SWT.BOLD));

// Class trong tham số, và vị trí ảnh cùng nằm trên 1 file Jar.
ImageDescriptor imageDescriptor = ImageDescriptor.createFromFile(
       ResourceDemo.class,
       "/org/o7planning/tutorial/jface/image/check.png");

Image image = jfaceRsManager.createImage(imageDescriptor);
Toàn bộ code của ResourceDemo.
package org.o7planning.tutorial.jface.rs;

import org.eclipse.jface.resource.FontDescriptor;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.wb.swt.SWTResourceManager;

public class ResourceDemo {

   protected Shell shlResourceDemo;

   /**
    * Launch the application.
    *
    * @param args
    */
   public static void main(String[] args) {
       try {
           ResourceDemo window = new ResourceDemo();
           window.open();
       } catch (Exception e) {
           e.printStackTrace();
       }
   }

   /**
    * Open the window.
    */
   public void open() {
       Display display = Display.getDefault();
       createContents();
       shlResourceDemo.open();
       shlResourceDemo.layout();
       while (!shlResourceDemo.isDisposed()) {
           if (!display.readAndDispatch()) {
               display.sleep();
           }
       }
   }

   /**
    * Create contents of the window.
    */
   protected void createContents() {
       shlResourceDemo = new Shell();
       shlResourceDemo.setSize(336, 249);
       shlResourceDemo.setText("Resource Demo");
       shlResourceDemo.setLayout(new RowLayout(SWT.HORIZONTAL));

       Button btnButtonU = new Button(shlResourceDemo, SWT.NONE);
       btnButtonU.setFont(SWTResourceManager.getFont("Arial", 12, SWT.NORMAL));
       btnButtonU.setForeground(SWTResourceManager.getColor(SWT.COLOR_BLUE));
       btnButtonU.setImage(SWTResourceManager.getImage(ResourceDemo.class,
               "/org/o7planning/tutorial/jface/image/check.png"));
       btnButtonU.setText("Button using SWT Resource Manager");

       //

       Button button2 = new Button(shlResourceDemo, SWT.NONE);
       button2.setText("Button using JFace Resource Manager");

       LocalResourceManager jfaceRsManager = new LocalResourceManager(
               JFaceResources.getResources(), shlResourceDemo);

       
       Color color = jfaceRsManager.createColor(new RGB(200, 100, 0));
       Font font = jfaceRsManager.createFont(FontDescriptor.createFrom(
               "Arial", 10, SWT.BOLD));
       
       ImageDescriptor imageDescriptor = ImageDescriptor.createFromFile(
               ResourceDemo.class,
               "/org/o7planning/tutorial/jface/image/check.png");
       Image image = jfaceRsManager.createImage(imageDescriptor);

       button2.setFont(font);
       button2.setForeground(color);
       button2.setImage(image);
   }
}

6- Sử dụng Control Decoration

Decoration là một Widget dùng để trang trí trong một số tình huống cho các Widget khác. Chẳng hạn để dánh dấu một trường Text bắt buộc phải nhập,...
  • Package: org.o7planning.tutorial.jface.decoration
  • Name: DecorationDemo
DecorationDemo.java
package org.o7planning.tutorial.jface.decoration;

import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import swing2swt.layout.FlowLayout;

public class DecorationDemo {

  protected Shell shlDecorationDemo;
  private Text text;

  /**
   * Launch the application.
   * @param args
   */
  public static void main(String[] args) {
      try {
          DecorationDemo window = new DecorationDemo();
          window.open();
      } catch (Exception e) {
          e.printStackTrace();
      }
  }

  /**
   * Open the window.
   */
  public void open() {
      Display display = Display.getDefault();
      createContents();
      shlDecorationDemo.open();
      shlDecorationDemo.layout();
      while (!shlDecorationDemo.isDisposed()) {
          if (!display.readAndDispatch()) {
              display.sleep();
          }
      }
  }

  /**
   * Create contents of the window.
   */
  protected void createContents() {
      shlDecorationDemo = new Shell();
      shlDecorationDemo.setSize(327, 245);
      shlDecorationDemo.setText("Decoration Demo");
      shlDecorationDemo.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
     
      text = new Text(shlDecorationDemo, SWT.BORDER);
     
      ControlDecoration controlDecoration = new ControlDecoration(text, SWT.LEFT | SWT.TOP);
     
      controlDecoration.setDescriptionText("Some description");
     
      Image image = FieldDecorationRegistry.
                getDefault().
                getFieldDecoration(FieldDecorationRegistry.DEC_ERROR_QUICKFIX).
                getImage();
     
      controlDecoration.setImage(image);
  }

}
Kết quả chạy class DecorationDemo:

7- JFace Viewer

SWT cung cấp một số control
  • List
  • Combo
  • Table
  • Tree
Mà việc sử dụng nó thực sự khó khăn, và việc code là dài dòng. Chẳng hạn khi làm việc với Table, khi hiển thị dữ liệu, bạn cần add từng TableItem vào Table. Mỗi TableItem là một dòng (row) của Table.  Việc thêm bớt row cũng phải dài dòng tương tự.
Nguyên tắc của JFace là tạo ra một Viewer. Viewer bao lấy control, và như vậy thay vì làm việc với control chúng ta làm việc với Viewer. Viewer đã giúp bạn ẩn đi việc sử lý hiển thị dữ liệu. Bạn chỉ cần cung cấp Content ProviderLabel Provider cho viewer thông qua method.
  • Viewer.setContentProvider(IContentProvider)
  • Viewer.setLabelProvider(IBaseLabelProvider)
Sét dự liệu đầu vào cho control thông qua method:
  • Viewer.setInput(Object)
Trong đó:

Content Provider:
  • Là class thi hành interface IContentProvider, nó nói cho Viewer cách sử dụng dữ liệu từ đầu vào, tách dữ liệu đó ra thành một mảng các Object, mỗi Object là dữ liệu 1 dòng (của Table, Tree, Combo hoặc List).
Label Provider:
  • Là class thi hành interface IBaseLabelProvider, nói cho Viewer biết cách từ việc có 1 Object dữ liệu 1 dòng, tại cột có chỉ số nào đó (columnIndex) sẽ hiển thị Image, Text gì.

7.1- Một số class tham gia trong demo

Có một vài class tham gia vào các ví dụ trong tài liệu này, nó được dùng nhiều lần.

Model:

AppMenu.java
package org.o7planning.tutorial.jface.model;

import java.util.List;

public class AppMenu {

  private String menuName;
  private String menuTitle;
  private List<AppMenu> children;

  public AppMenu(String menuName, String menuTitle, List<AppMenu> children) {
      this.menuName = menuName;
      this.menuTitle = menuTitle;
      this.children = children;
  }

  public String getMenuName() {
      return menuName;
  }

  public void setMenuName(String menuName) {
      this.menuName = menuName;
  }

  public String getMenuTitle() {
      return menuTitle;
  }

  public void setMenuTitle(String menuTitle) {
      this.menuTitle = menuTitle;
  }

  public List<AppMenu> getChildren() {
      return children;
  }

}
Article.java
package org.o7planning.tutorial.jface.model;

public class Article {

  private String title;
  private String author;
  private boolean published;

  public Article(String title, String author, boolean published) {
      this.title = title;
      this.author = author;
      this.published = published;
  }

  public String getTitle() {
      return title;
  }

  public void setTitle(String title) {
      this.title = title;
  }

  public String getAuthor() {
      return author;
  }

  public void setAuthor(String author) {
      this.author = author;
  }

  public boolean isPublished() {
      return published;
  }

  public void setPublished(boolean published) {
      this.published = published;
  }

}
Employee.java
package org.o7planning.tutorial.jface.model;

public class Employee {

  private String empNo;
  private String firstName;
  private String lastName;

  public Employee(String empNo, String firstName, String lastName) {
      this.empNo = empNo;
      this.firstName = firstName;
      this.lastName = lastName;
  }

  public String getEmpNo() {
      return empNo;
  }

  public void setEmpNo(String empNo) {
      this.empNo = empNo;
  }

  public String getFirstName() {
      return firstName;
  }

  public void setFirstName(String firstName) {
      this.firstName = firstName;
  }

  public String getLastName() {
      return lastName;
  }

  public void setLastName(String lastName) {
      this.lastName = lastName;
  }
}
Department.java
package org.o7planning.tutorial.jface.model;

import java.util.List;

public class Department {

  private String deptNo;
  private String deptName;
  private List<Employee> employees;

  public Department(String deptNo, String deptName, List<Employee> employees) {
      this.deptNo = deptNo;
      this.deptName = deptName;
      this.employees = employees;
  }

  public String getDeptNo() {
      return deptNo;
  }

  public void setDeptNo(String deptNo) {
      this.deptNo = deptNo;
  }

  public String getDeptName() {
      return deptName;
  }

  public void setDeptName(String deptName) {
      this.deptName = deptName;
  }

  public List<Employee> getEmployees() {
      return employees;
  }

}
DataModel.java
package org.o7planning.tutorial.jface.model;

import java.util.ArrayList;
import java.util.List;

public class DataModel {

  private static List<Article> articleList;
  private static List<Department> departmentList;
  private static List<AppMenu> appMenuList;

  public static List<Article> getArticles() {
      if (articleList == null) {
          articleList = new ArrayList<Article>();
          articleList.add(new Article("Java basic", "Tom", true));
          articleList
                  .add(new Article("Hibernate for beginners", "Tran", true));
          articleList.add(new Article("Maven for beginners", "Smith", false));
      }
      return articleList;
  }

  public static List<Department> getDepartments() {
      if (departmentList == null) {

          Employee emp11 = new Employee("E11", "Michael", "Smith");
          Employee emp12 = new Employee("E12", "Susan", "Barker");
          List<Employee> empList1 = new ArrayList<Employee>();
          empList1.add(emp11);
          empList1.add(emp12);

          Department dept1 = new Department("D01", "Operation", empList1);
          //
          Employee emp21 = new Employee("E21", "Robert", "Tyler");
          List<Employee> empList2 = new ArrayList<Employee>();
          empList2.add(emp21);

          Department dept2 = new Department("D02", "Adminstration", empList2);
          //
          departmentList = new ArrayList<Department>();

          departmentList.add(dept1);
          departmentList.add(dept2);
      }
      return departmentList;
  }

  public static List<AppMenu> getAppMenus() {
      if (appMenuList == null) {
          appMenuList = new ArrayList<AppMenu>();

          AppMenu appMenu31 = new AppMenu("ErrorLog", "Error Log", null);
          AppMenu appMenu32 = new AppMenu("ProjectExplorer",
                  "Project Explorer", null);

          List<AppMenu> list3 = new ArrayList<AppMenu>();
          list3.add(appMenu31);
          list3.add(appMenu32);

          AppMenu appMenu21 = new AppMenu("ShowView", "Show View", list3);
          AppMenu appMenu22 = new AppMenu("ClosePerspective",
                  "Close perspective...", null);
          List<AppMenu> list2 = new ArrayList<AppMenu>();
          list2.add(appMenu21);
          list2.add(appMenu22);

          AppMenu appMenu1 = new AppMenu("Window", "Window", list2);

          appMenuList.add(appMenu1);
      }
      return appMenuList;
  }

}

Content/Label Provider:

AbstractComboContentLabelProvider.java
package org.o7planning.tutorial.jface.provider;

import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;

public abstract class AbstractComboContentLabelProvider implements
      IStructuredContentProvider, ILabelProvider {

  @Override
  public void dispose() {

  }

  @Override
  public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {

  }

  @Override
  public void addListener(ILabelProviderListener listener) {
  }

  @Override
  public boolean isLabelProperty(Object element, String property) {
      return false;
  }

  @Override
  public void removeListener(ILabelProviderListener listener) {

  }

  @Override
  public Image getImage(Object element) {
      return null;
  }
}
AbstractTableContentLabelProvider.java
package org.o7planning.tutorial.jface.provider;

import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;

public abstract class AbstractTableContentLabelProvider implements
      ITableLabelProvider, IStructuredContentProvider {

  @Override
  public void dispose() {

  }

  @Override
  public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {

  }

  @Override
  public void addListener(ILabelProviderListener listener) {

  }

  @Override
  public boolean isLabelProperty(Object element, String property) {
      return false;
  }

  @Override
  public void removeListener(ILabelProviderListener listener) {

  }

  @Override
  public Image getColumnImage(Object element, int columnIndex) {
      return null;
  }

}
AbstractTreeContentLabelProvider.java
package org.o7planning.tutorial.jface.provider;

import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;

public abstract class AbstractTreeContentLabelProvider implements
      ITreeContentProvider, ILabelProvider {

  @Override
  public void dispose() {

  }

  @Override
  public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {

  }

  @Override
  public Object getParent(Object element) {
      return null;
  }

  @Override
  public void addListener(ILabelProviderListener listener) {

  }

  @Override
  public boolean isLabelProperty(Object element, String property) {
      return false;
  }

  @Override
  public void removeListener(ILabelProviderListener listener) {
  }

  @Override
  public Image getImage(Object element) {
      return null;
  }

}
AbstractTreeTableContentLabelProvider.java
package org.o7planning.tutorial.jface.provider;

import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;

public abstract class AbstractTreeTableContentLabelProvider implements
      ITreeContentProvider, ITableLabelProvider {

  @Override
  public void dispose() {
  }

  @Override
  public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
  }

  @Override
  public void addListener(ILabelProviderListener listener) {
  }

  @Override
  public boolean isLabelProperty(Object element, String property) {
      return false;
  }

  @Override
  public void removeListener(ILabelProviderListener listener) {
  }

  @Override
  public Image getColumnImage(Object element, int columnIndex) {
      return null;
  }

  @Override
  public Object getParent(Object element) {
      return null;
  }

}

7.2- JFace TableViewer

Với TableViewer. Content/Label Provider nên sử dụng là:
  • Content Provider: implements IStructuredContentProvider
  • Label Provider: implements ITableLabelProvider
  • File/New/Other...
Nhập vào:
  • Package: org.o7planning.tutorial.jface.tableviewer1
  • Name: TableViewerDemo
  • Chọn: protected createContents() method
    • (Code sẽ được tạo ra để trong method này).
Sét đặt Layout là FillLayout cho đối tượng shell bằng cách chọn biểu tượng FillLayout và click vào màn hình Shell.
Tạo 2 cột cho bảng bằng cách chọn biểu tượng TableColumn và bỏ vào màn hình, đồng thời thay đổi tiêu đề cột như hình minh họa dưới đây.
Class ArticleTableCLProvider extends từ class AbstractTableContentLabelProvider, nó có tính năng của Content ProviderLabel Provider.
ArticleTableCLProvider.java
package org.o7planning.tutorial.jface.tableviewer1;

import java.util.List;

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.o7planning.tutorial.jface.model.Article;
import org.o7planning.tutorial.jface.provider.AbstractTableContentLabelProvider;

public class ArticleTableCLProvider extends AbstractTableContentLabelProvider {

  private Image image;

  public ArticleTableCLProvider() {
      LocalResourceManager jfaceRsManager = new LocalResourceManager(
              JFaceResources.getResources(),
              Display.getCurrent().getShells()[0]);

      ImageDescriptor imageDescriptor = ImageDescriptor.createFromFile(
              ArticleTableCLProvider.class,
              "/org/o7planning/tutorial/jface/image/check.png");
      image = jfaceRsManager.createImage(imageDescriptor);
  }

  @Override
  public String getColumnText(Object element, int columnIndex) {
      Article article = (Article) element;
      switch (columnIndex) {

      case 0:// 0 - Ứng với cột đầu tiên.
          return article.getTitle();

      case 1:// 1 - Ứng với cột thứ 2
          return article.getAuthor();
      default:
          return null;
      }
  }

  @Override
  public Image getColumnImage(Object element, int columnIndex) {
      Article article = (Article) element;
      switch (columnIndex) {

      case 0:// 0 - Ứng với cột đầu tiên.
          if (article.isPublished()) {
              return image;
          }
      default:
          return null;
      }
  }

  // input tại đây có được từ viewer.setInput(...)
  @Override
  public Object[] getElements(Object input) {
      List<Article> list = (List<Article>) input;
      return list.toArray();
  }

}
Mở code của class TableViewerDemo, để thêm vào một số đoạn code.
//
ArticleTableCLProvider provider = new ArticleTableCLProvider();        
tableViewer.setContentProvider(provider);        
tableViewer.setLabelProvider(provider);  

// Sét đặt dữ liệu vào TableViewer.
List<Article> articleList= DataModel.getArticles();
tableViewer.setInput(articleList);
Giống hình minh họa dưới đây.
Và đây là kết quả chạy class TableViewerDemo:
Toàn bộ code class TableViewerDemo:
TableViewerDemo.java
package org.o7planning.tutorial.jface.tableviewer1;

import java.util.List;

import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.o7planning.tutorial.jface.model.Article;
import org.o7planning.tutorial.jface.model.DataModel;

public class TableViewerDemo {

  protected Shell shlTableviewerdemo;
  private Table table;

  /**
   * Launch the application.
   * @param args
   */
  public static void main(String[] args) {
      try {
          TableViewerDemo window = new TableViewerDemo();
          window.open();
      } catch (Exception e) {
          e.printStackTrace();
      }
  }

  /**
   * Open the window.
   */
  public void open() {
      Display display = Display.getDefault();
      createContents();
      shlTableviewerdemo.open();
      shlTableviewerdemo.layout();
      while (!shlTableviewerdemo.isDisposed()) {
          if (!display.readAndDispatch()) {
              display.sleep();
          }
      }
  }

  /**
   * Create contents of the window.
   */
  protected void createContents() {
      shlTableviewerdemo = new Shell();
      shlTableviewerdemo.setSize(366, 277);
      shlTableviewerdemo.setText("TableViewerDemo");
      shlTableviewerdemo.setLayout(new FillLayout(SWT.HORIZONTAL));
     
      TableViewer tableViewer = new TableViewer(shlTableviewerdemo, SWT.BORDER | SWT.FULL_SELECTION);        
     
      // Content Provider & Label Provider.
      ArticleTableCLProvider provider = new ArticleTableCLProvider();        
      tableViewer.setContentProvider(provider);        
      tableViewer.setLabelProvider(provider);        
     
      table = tableViewer.getTable();
      table.setLinesVisible(true);
      table.setHeaderVisible(true);
     
      TableColumn tblclmnNewColumn = new TableColumn(table, SWT.NONE);
      tblclmnNewColumn.setWidth(148);
      tblclmnNewColumn.setText("Article");
     
      TableColumn tblclmnNewColumn_1 = new TableColumn(table, SWT.NONE);
      tblclmnNewColumn_1.setWidth(119);
      tblclmnNewColumn_1.setText("Author");
     
      // Dữ liệu được sét đặt vào TableViewer.
      List<Article> articleList= DataModel.getArticles();
      tableViewer.setInput(articleList);

  }

}

Trường hợp thêm, xóa dòng dữ liệu trên bảng.

// Lấy ra dữ liệu của TableViewer.
List<Article> input = (List<Article>)tableViewer.getInput();

// Thêm dòng.
Article newArticle = .... ;
input.add(newArticle);

// Refresh lại
tableViewer.refresh(newArticle);
// hoặc
tableViewer.refresh();

// Trường hợp xóa 1 dòng dữ liệu
input.remove(<article>);

tableViewer.refresh();

7.3- JFace Tree Table Viewer

Với TreeViewer hiển thị dữ liệu vừa là Tree vừa là Table. Content/Label Provider nên sử dụng là:
  • Content Provider: implements ITreeContentProvider
  • Label Provider: implements ITableLabelProvider
Ví dụ:
DeptEmpTreeTableCLProvider.java
package org.o7planning.tutorial.jface.treetable1;

import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.o7planning.tutorial.jface.model.Department;
import org.o7planning.tutorial.jface.model.Employee;
import org.o7planning.tutorial.jface.provider.AbstractTreeTableContentLabelProvider;

public class DeptEmpTreeTableCLProvider extends
     AbstractTreeTableContentLabelProvider {

 private Image EMP_IMAGE;
 private Image DEPT_IMAGE;

 public DeptEmpTreeTableCLProvider() {
    // Dùng tạm ảnh của có sẵn trong hệ thống để minh họa
   
     DEPT_IMAGE = Display.getCurrent().getSystemImage(SWT.ICON_INFORMATION);
   
     EMP_IMAGE = Display.getCurrent().getSystemImage(SWT.ICON_ERROR  );
 }

 @Override
 public Object[] getElements(Object inputElement) {
     List<Department> departments = (List<Department>) inputElement;
     return departments.toArray();
 }

 @Override
 public Object[] getChildren(Object parentElement) {
     if (parentElement instanceof Department) {
         Department dept = (Department) parentElement;
         List<Employee> emps = dept.getEmployees();
         return emps == null ? null : emps.toArray();
     } else {
         // Employee has no children
         return null;
     }
 }

 @Override
 public boolean hasChildren(Object element) {
     if (element instanceof Department) {
         Department dept = (Department) element;
         List<Employee> emps = dept.getEmployees();
         return emps != null && !emps.isEmpty();
     } else {
         // Employee has no children
         return false;
     }
 }

 @Override
 public String getColumnText(Object element, int columnIndex) {
     if (element instanceof Department) {
         Department dept = (Department) element;
         switch (columnIndex) {
         case 0:
             return dept.getDeptNo();
         case 1:
             return dept.getDeptName();
         default:
             return null;
         }
     } else {
         Employee emp = (Employee) element;
         switch (columnIndex) {
         case 2:
             return emp.getEmpNo();
         case 3:
             return emp.getFirstName();
         case 4:
             return emp.getLastName();
         default:
             return null;
         }
     }
 }

 @Override
 public Image getColumnImage(Object element, int columnIndex) {
     if (element instanceof Department) {
         switch (columnIndex) {
         case 0:
             return DEPT_IMAGE;
         default:
             return null;
         }
     } else {
         switch (columnIndex) {
         case 2:
             return EMP_IMAGE;
         default:
             return null;
         }
     }
 }

}
Sửa code trên class TreeTableViewerDemo:
Xem toàn bộ code của class TreeTableViewerDemo:
TreeTableViewerDemo.java
package org.o7planning.tutorial.jface.treetable1;

import org.eclipse.swt.widgets.Display;

public class TreeTableViewerDemo {

  protected Shell shlTreeTableViewer;

  /**
   * Launch the application.
   * @param args
   */
  public static void main(String[] args) {
      try {
          TreeTableViewerDemo window = new TreeTableViewerDemo();
          window.open();
      } catch (Exception e) {
          e.printStackTrace();
      }
  }

  /**
   * Open the window.
   */
  public void open() {
      Display display = Display.getDefault();
      createContents();
      shlTreeTableViewer.open();
      shlTreeTableViewer.layout();
      while (!shlTreeTableViewer.isDisposed()) {
          if (!display.readAndDispatch()) {
              display.sleep();
          }
      }
  }

  /**
   * Create contents of the window.
   */
  protected void createContents() {
      shlTreeTableViewer = new Shell();
      shlTreeTableViewer.setSize(438, 226);
      shlTreeTableViewer.setText("Tree Table Viewer");
      shlTreeTableViewer.setLayout(new FillLayout(SWT.HORIZONTAL));
     
      TreeViewer treeViewer = new TreeViewer(shlTreeTableViewer, SWT.BORDER);
     
      DeptEmpTreeTableCLProvider provider= new DeptEmpTreeTableCLProvider();
      treeViewer.setContentProvider(provider);
      treeViewer.setLabelProvider(provider);
             
      Tree tree = treeViewer.getTree();
      tree.setLinesVisible(true);
      tree.setHeaderVisible(true);
     
      TreeColumn trclmnDeptNo = new TreeColumn(tree, SWT.NONE);
      trclmnDeptNo.setWidth(71);
      trclmnDeptNo.setText("Dept No");
     
      TreeColumn trclmnDeptName = new TreeColumn(tree, SWT.NONE);
      trclmnDeptName.setWidth(79);
      trclmnDeptName.setText("Dept Name");
     
      TreeColumn trclmnEmpNo = new TreeColumn(tree, SWT.NONE);
      trclmnEmpNo.setWidth(69);
      trclmnEmpNo.setText("Emp No");
     
      TreeColumn trclmnFirstName = new TreeColumn(tree, SWT.NONE);
      trclmnFirstName.setWidth(77);
      trclmnFirstName.setText("First Name");
     
      TreeColumn trclmnLastName = new TreeColumn(tree, SWT.NONE);
      trclmnLastName.setWidth(100);
      trclmnLastName.setText("Last Name");
     
      treeViewer.setInput(DataModel.getDepartments());
  }

}
Kết quả chạy ví dụ:

Thêm xóa dòng dữ liệu trên TreeViewer

// Lấy ra dữ liệu của TreeViewer.
List<Department> input = (List<Department>)treeViewer.getInput();

Department dept =  input.get(0);
List<Employee> empList  = dept.getEmployees();

// Thêm employee vào Department.
empList.add(newEmployee);

// Refresh
treeViewer.refresh(dept);
// Hoặc
treeViewer.refresh();

// Xóa cũng tương tự.

7.4- JFace TreeViewer

Với TreeViewer hiển thị dữ liệu vừa là Tree vừa là Table. Content/Label Provider nên sử dụng là:
  • Content Provider: implements ITreeContentProvider
  • Label Provider: implements ITableLabelProvider
Trong trường hợp Tree (1 cột không phải Table):
  • Content Provider: implements ITreeContentProvider
  • Label Provider: implements ILabelProvider

Note: Interface ITableLabelProvider extends from interface ILabelProvider

Ví dụ:
Bạn có thể thêm 1 TreeColumn vào Tree. Hoặc không cần một TreeColumn nào cả. Minh họa dưới đây tôi sử dụng Tree không có TreeColumn.

Việc Tree có Column, bạn có thể sét tiêu đề cho cột, nhưng nhiều tình huống điều đó là không cần thiết.

AppMenuTreeCLProvider.java
package org.o7planning.tutorial.jface.treeviewer1;

import java.util.List;

import org.o7planning.tutorial.jface.model.AppMenu;
import org.o7planning.tutorial.jface.provider.AbstractTreeContentLabelProvider;

public class AppMenuTreeCLProvider extends AbstractTreeContentLabelProvider {

  @Override
  public String getText(Object element) {
      AppMenu appMenu= (AppMenu) element;
      return appMenu.getMenuTitle();
  }

  @Override
  public Object[] getElements(Object inputElement) {
      List<AppMenu> menus = (List<AppMenu>) inputElement;
      return menus.toArray();
  }

  @Override
  public Object[] getChildren(Object parentElement) {
       AppMenu menu= (AppMenu) parentElement;
       List<AppMenu> children= menu.getChildren();
       return children== null? null: children.toArray();
  }

  @Override
  public boolean hasChildren(Object element) {
       AppMenu menu= (AppMenu) element;
       List<AppMenu> children= menu.getChildren();
       return children!= null&&!children.isEmpty();
  }

}
TreeViewerDemo.java
package org.o7planning.tutorial.jface.treeviewer1;

import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.o7planning.tutorial.jface.model.DataModel;

public class TreeViewerDemo {

  protected Shell shlTreeviewerDemo;

  /**
   * Launch the application.
   * @param args
   */
  public static void main(String[] args) {
      try {
          TreeViewerDemo window = new TreeViewerDemo();
          window.open();
      } catch (Exception e) {
          e.printStackTrace();
      }
  }

  /**
   * Open the window.
   */
  public void open() {
      Display display = Display.getDefault();
      createContents();
      shlTreeviewerDemo.open();
      shlTreeviewerDemo.layout();
      while (!shlTreeviewerDemo.isDisposed()) {
          if (!display.readAndDispatch()) {
              display.sleep();
          }
      }
  }

  /**
   * Create contents of the window.
   */
  protected void createContents() {
      shlTreeviewerDemo = new Shell();
      shlTreeviewerDemo.setSize(246, 202);
      shlTreeviewerDemo.setText("TreeViewer Demo");
      shlTreeviewerDemo.setLayout(new FillLayout(SWT.HORIZONTAL));
     
      TreeViewer treeViewer = new TreeViewer(shlTreeviewerDemo, SWT.BORDER);
     
      AppMenuTreeCLProvider provider= new AppMenuTreeCLProvider();
      treeViewer.setContentProvider(provider);
      treeViewer.setLabelProvider(provider);
     
      Tree tree = treeViewer.getTree();
      tree.setLinesVisible(true);
      tree.setHeaderVisible(true);
     
      treeViewer.setInput(DataModel.getAppMenus());
  }
}
Kết quả chạy ví dụ:

Thêm, xóa dòng dữ liệu trên TreeViewer

// Lấy ra dữ liệu của TreeViewer.
List<AppMenu> input = (List<AppMenu>)treeViewer.getInput();

AppMenu menu =  input.get(0);
List<AppMenu> childMenus = menu.getChildren();

// Thêm vào AppMenu
childMenus .add(newAppMenu);

// Refresh
treeViewer.refresh(menu );
// Hoặc
treeViewer.refresh();

// Xóa cũng tương tự.

7.5- JFace CheckboxTableViewer

  • Package: org.o7planning.tutorial.jface.cbtableviewer
  • Name: CheckboxTableViewerDemo
  • TODO...