2014年3月25日 星期二

JavaFX 8 Event with Lambda Expression

Lambda Expression是Java SE 8.0新增的一項語言描述方式,其語法如下


(argument) -> (body)


Lambda Expression是一種匿名函數 (Anonymous Function),沒有Method Declaration (方法宣告),亦不需要Modifier (修飾詞) 與Return Value Declaration (回傳值宣告) 等,因此程式更為精簡。

以下是一些簡單的例子


(int a, int b) -> {return a + b;}

() -> System.out.println("...");

(String value) -> {return value;}


我們可以將Lambda Expression運用於JavaFX 8的事件處理上,讓處理事件的方式更為簡單

首先回顧JavaFX 2處理事件的程式架構

JavaFX 2簡化處理事件的方式,不像Java以不同的Listener介面處理各類事件,JavaFX 2僅以EventHandler介面處理各類事件,且介面僅提供handle()方法,並以事件類型 (Event Type) 定義各類事件,其基礎類別為javafx.event.Event,繼承自Event類別的事件類別分別如下所示,其中較特殊的是手勢與觸控事件:
  • ActionEvent:動作事件。
  • ContextMenuEvent:快顯選單事件。
  • DragEvent:拖曳事件,適用於滑鼠與觸控裝置。
  • GestureEvent:手勢事件,適用於觸控裝置。
  • InputEvent:輸入事件。
  • InputMethodEvent輸入方法事件。
  • KeyEvent按鍵事件。
  • MediaErrorEvent多媒體錯誤事件。
  • MouseEvent滑鼠事件。
  • MouseDragEvent滑鼠拖曳事件,有別於DragEvent。
  • RotateEvent旋轉事件,適用於觸控裝置。
  • ScrollEvent捲動事件,適用於滑鼠與觸控裝置。
  • SwipeEvent滑動事件,適用於觸控裝置。
  • TouchEvent觸控事件,適用於觸控裝置。
  • WebEventWeb Engine事件。
  • WindowEvent視窗事件。
  • WorkerStateEventWorker狀態改變時之事件。
  • ZoomEvent縮放事件,適用於觸控裝置。
JavaFX 2處理事件的第一種方式是以物件的setOnXXX()方法設定處理事件的Event Handler函式,其語法如下,其中[Event_TYPE]為上述之事件類別:


[object].setOnXXX(new EventHandler<[Event_TYPE]>() {
  @Override public void handle([Event_TYPE] e) {
    ...
  }
});


以按鈕的動作事件為例,其設定Event Handler函式的方法為setOnAction()、事件類別為ActionEvent


Button button = new Button();

button.setOnAction(new EventHandler<ActionEvent>() {

  @Override public void handle(ActionEvent e) {
    ...
  }
});


亦可使用建立類別的方式處理:


Button button = new Button();
button.setOnAction(onActionEventHandler);
...

EventHandler onActionEventHandler = new EventHandler<ActionEvent>() {

  @Override public void handle(ActionEvent e) {
    ...
  }
};


透過Lambda Expression可將上述程式精簡如下,省略EventHandler介面的描述


Button button = new Button();

button.setOnAction(
(ActionEvent e) -> {
  ...
});


或以建立類別的方式處理:


Button button = new Button();
button.setOnAction(onActionEventHandler);
...

EventHandler onActionEventHandler = 

  (EventHandler<ActionEvent>)(ActionEvent e) -> {
  ...
};


更進一步可依賴編譯器的型態推斷 (Type Inference),讓程式更精簡

Button button = new Button();

button.setOnAction(e -> {
  ...
});


以上由良葛格指導,特別在此感謝良葛格。

JavaFX 2處理事件的第二種方式是以物件的addEventHandler()方法註冊事件的Event Handler,其語法如下,其中[eventType]代表事件類型、[Event_TYPE]為前述之事件類別:


[object].addEventHandler([eventType], new EventHandler<[Event_TYPE]>() {
  @Override public void handle([Event_TYPE] e) {
    ...
  }
});


以按鈕的動作事件為例,其事件類型為ActionEvent.ACTION、事件類別為ActionEvent,註冊Event Handler的程式架構如下:


Button button = new Button();

button.addEventHandler(ActionEvent.ACTION,

  new EventHandler<ActionEvent>() {
    @Override public void handle(ActionEvent e) {
      ...
    }
  }
);


透過Lambda Expression可將上述程式精簡如下


Button button = new Button();

button.addEventHandler(ActionEvent.ACTION, (ActionEvent e) -> {
  ...
};


JavaFX 2處理事件的第三種方式是以物件的addEventFilter()方法註冊事件的Event Filter,其語法如下,與Event Handler幾乎一樣,其中[eventType]代表事件類型、[Event_TYPE]為前述之事件類別:


[object].addEventFilter([eventType], new EventHandler<[Event_TYPE]>() {
  @Override public void handle([Event_TYPE] e) {
    ...
  }
});


以按鈕的動作事件為例,其事件類型為ActionEvent.ACTION、事件類別為ActionEvent,註冊Event Filter的程式架構如下:


Button button = new Button();

button.addEventFilter(ActionEvent.ACTION,

  new EventHandler<ActionEvent>() {
    @Override public void handle(ActionEvent e) {
      ...
    }
  }
);


透過Lambda Expression可將上述程式精簡如下


Button button = new Button();

button.addEventFilter(ActionEvent.ACTION, (ActionEvent e) -> {
  ...
};


【參考資料】

[1] 黃嘉輝,深入研究JavaFX 2。
[2] Java Official Web Site:http://www.oracle.com/technetwork/java/index.html
[3] JavaFX:http://www.oracle.com/technetwork/java/javafx
[4] JavaFX 8.0 API Specification.
[5] Java Platform, Standard Edition 8 API Specification.

© Chia-Hui Huang

沒有留言:

張貼留言