2014年2月22日 星期六

JavaFX Event (2) Key Event

接著上一篇JavaFX Event (1) Introduction介紹JavaFX處理事件基本概念,本篇將說明按鍵事件

按鍵事件 (Key Event) 是當使用者按下或放開鍵盤按鍵時所產生的事件,除了A~Z與0~9等按鍵之外,最常處理的按鍵包括上下左右鍵、Page Up、Page Down、Alt、Shift、Ctrl等特殊功能鍵。

按鍵事件包括按下鍵盤按鍵 (Pressed)、放開鍵盤按鍵 (Released) 與按下並放開鍵盤按鍵 (Typed) 等三種,前兩者為低階 (Low-Level) 並與作業平台及鍵盤配置有關的事件,後者則是高階 (High-Level) 並與作業平台及鍵盤配置無關的事件。

JavaFX按鍵事件的類別為KeyEvent,繼承自InputEvent類別,按鍵事件為Node抽象類別與Scene類別所定義之事件,因此凡繼承Node抽象類別的物件,均會產生按鍵事件。

按鍵事件可分別以setOnKeyPressed()setOnKeyReleased()setOnKeyTyped()方法設定按下鍵盤按鍵、放開鍵盤按鍵與按下並放開鍵盤按鍵的Event Handler函式。

KeyEvent類別定義以下的事件類型,以做為註冊Event Handler與Event Filter之用:
  • KeyEvent.KEY_PRESSED:按下鍵盤按鍵。
  • KeyEvent.KEY_RELEASED:放開鍵盤按鍵。
  • KeyEvent.KEY_TYPED:按下並放開鍵盤按鍵。
  • KeyEvent.ANY:代表上述任一種事件類型。
請參考以下範例,介紹如何處理鍵盤按鍵事件,範例分別以setOnKeyPressed()setOnKeyReleased()setOnKeyTyped()方法設定按下鍵盤按鍵、放開鍵盤按鍵與按下並放開鍵盤按鍵的Event Handler函式。

setOnKeyPressed()設定為例,分別以isAltDown()isControlDown()isShiftDown()方法判斷是否按下Alt鍵、Ctrl鍵與Shift鍵,此外並以getCode()方法取得按鍵值,判斷是否按下上下左右鍵、上一頁與下一頁按鍵,藉此移動視窗:


// Key Pressed
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
  @Override public void handle(KeyEvent e) {
    int dx = 0;
    int dy = 0;

    // 判斷是否按下Alt鍵
    if (e.isAltDown()) 
      label.setText("Press Alt key") ;

    // 判斷是否按下Ctrl鍵
    if (e.isControlDown()) 
      label.setText("Press Control key") ;

    // 判斷是否按下Shift鍵
    if (e.isShiftDown()) 
      label.setText("Press Shift key") ;

    label.setText("Press " + e.getCode().getName()) ;
    
    // 取得按鍵按鍵值,判斷是否按下上下左右鍵、上一頁與下一頁按鍵
    if (e.getCode() == KeyCode.UP)
      dy = -5;
    else if (e.getCode() == KeyCode.DOWN) 
      dy = 5;
    else if (e.getCode() == KeyCode.LEFT) 
      dx = -5;
    else if (e.getCode() == KeyCode.RIGHT) 
      dx = 5;
    else if (e.getCode() == KeyCode.PAGE_UP) 
      dy = -100;
    else if (e.getCode() == KeyCode.PAGE_DOWN) 
      dy = 100;
    
    stage.setX(stage.getX() + dx);
    stage.setY(stage.getY() + dy);
  }
});


除了上述語法之外,亦可以建立類別的方式處理,請參考以下範例:


// Key Pressed
scene.setOnKeyPressed(onKeyPressedEventHandler);
...

EventHandler onKeyPressedEventHandler = new EventHandler<KeyEvent>() {
  @Override public void handle(KeyEvent e) {
    int dx = 0;
    int dy = 0;

    // 判斷是否按下Alt鍵
    if (e.isAltDown()) 
      label.setText("Press Alt key") ;

    // 判斷是否按下Ctrl鍵
    if (e.isControlDown()) 
      label.setText("Press Control key") ;

    // 判斷是否按下Shift鍵
    if (e.isShiftDown()) 
      label.setText("Press Shift key") ;

    label.setText("Press " + e.getCode().getName()) ;
    
    // 取得按鍵按鍵值,判斷是否按下上下左右鍵、上一頁與下一頁按鍵
    if (e.getCode() == KeyCode.UP)
      dy = -5;
    else if (e.getCode() == KeyCode.DOWN) 
      dy = 5;
    else if (e.getCode() == KeyCode.LEFT) 
      dx = -5;
    else if (e.getCode() == KeyCode.RIGHT) 
      dx = 5;
    else if (e.getCode() == KeyCode.PAGE_UP) 
      dy = -100;
    else if (e.getCode() == KeyCode.PAGE_DOWN) 
      dy = 100;
    
    stage.setX(stage.getX() + dx);
    stage.setY(stage.getY() + dy);
  }
};


第二種方式是以addEventHandler()方法註冊事件的Event Handler,請參考以下範例,以按下鍵盤按鍵事件為例,其程式如下:


// Key Pressed
scene.addEventHandler(KeyEvent.KEY_PRESSED, 
  new EventHandler<KeyEvent>() {
  @Override public void handle(KeyEvent e) {
    int dx = 0;
    int dy = 0;

    // 判斷是否按下Alt鍵
    if (e.isAltDown()) 
      label.setText("Press Alt key") ;

    // 判斷是否按下Ctrl鍵
    if (e.isControlDown()) 
      label.setText("Press Control key") ;

    // 判斷是否按下Shift鍵
    if (e.isShiftDown()) 
      label.setText("Press Shift key") ;

    label.setText("Press " + e.getCode().getName()) ;
    
    // 取得按鍵按鍵值,判斷是否按下上下左右鍵、上一頁與下一頁按鍵
    if (e.getCode() == KeyCode.UP)
      dy = -5;
    else if (e.getCode() == KeyCode.DOWN) 
      dy = 5;
    else if (e.getCode() == KeyCode.LEFT) 
      dx = -5;
    else if (e.getCode() == KeyCode.RIGHT) 
      dx = 5;
    else if (e.getCode() == KeyCode.PAGE_UP) 
      dy = -100;
    else if (e.getCode() == KeyCode.PAGE_DOWN) 
      dy = 100;
    
    stage.setX(stage.getX() + dx);
    stage.setY(stage.getY() + dy);
  }
});


第三種方式是以addEventFilter()方法註冊事件的Event Filter,請參考以下範例,幾乎與上述範例一樣:


// Key Pressed
scene.addEventFilter(KeyEvent.KEY_PRESSED, 
  new EventHandler<KeyEvent>() {
  @Override public void handle(KeyEvent e) {
    int dx = 0;
    int dy = 0;

    // 判斷是否按下Alt鍵
    if (e.isAltDown()) 
      label.setText("Press Alt key") ;

    // 判斷是否按下Ctrl鍵
    if (e.isControlDown()) 
      label.setText("Press Control key") ;

    // 判斷是否按下Shift鍵
    if (e.isShiftDown()) 
      label.setText("Press Shift key") ;

    label.setText("Press " + e.getCode().getName()) ;
    
    // 取得按鍵按鍵值,判斷是否按下上下左右鍵、上一頁與下一頁按鍵
    if (e.getCode() == KeyCode.UP)
      dy = -5;
    else if (e.getCode() == KeyCode.DOWN) 
      dy = 5;
    else if (e.getCode() == KeyCode.LEFT) 
      dx = -5;
    else if (e.getCode() == KeyCode.RIGHT) 
      dx = 5;
    else if (e.getCode() == KeyCode.PAGE_UP) 
      dy = -100;
    else if (e.getCode() == KeyCode.PAGE_DOWN) 
      dy = 100;
    
    stage.setX(stage.getX() + dx);
    stage.setY(stage.getY() + dy);
  }
});


【參考資料】

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

© Chia-Hui Huang

沒有留言:

張貼留言