torutkのブログ

ソフトウェア・エンジニアのブログ

JavaFXで例えばButtonが押されたイベントを横取りするには

JavaFXで作成した画面上のあるコントロール(ButtonやRadioButtonなど)に対して入力操作(クリック等)が行われると対応するイベントが発生します。このイベントによってコントロールに結び付けられたアプリケーション側のメソッドが呼ばれます。

ここで、コントロールに結び付けられたメソッドが呼ばれる前にそのコントロールへのイベントを横取りしてちょっとした処理を差し込みたいとします。

方法は、以前の日記(id:torutk:20140602)で紹介した、JavaFXイベント処理の流れにおいてイベント補足(Event capturing)の段階で特定のコントロールへの入力操作のイベントを取得し、処理を入れ込みます。

ラジオボタン(RadioButton)をマウスでクリックした際に、そのイベントを横取りして標準出力にメッセージだけ吐いてイベントを握りつぶすコードの断片を次に示します。

public class RadioButtonFilterViewController implements Initializable {

    @FXML
    private RadioButton darkRadioButton;

      :(中略)

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        darkRadioButton.addEventFilter(
            MouseEvent.MOUSE_PRESSED, this::filterDarkRadioButton
        );
    }

    private void filterDarkRadioButton(Event e) {
        System.out.println("[Filter]Dark radio button event:" + e);
        e.consume();
    }
} 

RadioButtonクラスのaddEventFilterメソッドで、補足したいイベント種類と補足したときに実行したいハンドラ(メソッド)を指定します。ここでは、マウスクリックの最初のイベントであるマウスボタン押し下げイベント(MouseEvent.MOUSE_PRESSED)を指定しています。すると、ラジオボタンの領域でマウスボタン押し下げ操作をすると、addEventFilterメソッドで登録したハンドラが呼ばれます。このハンドラが終了すると、続いて本来ラジオボタンを押したときの処理が呼ばれます。ただし、ハンドラ中でEventのconsumeメソッドを呼ぶとそのイベントを握りつぶすことができます。

メモ

addEventFilterメソッドで指定するイベント種類をMouseEvent.MOUSE_CLICKEDにした場合、ハンドラ中でEventのconsumeメソッドを呼んでいても、本来のラジオボタンをクリックしたときの処理が走ります。これは、MOUSE_CLICKEDが実際はMOUSE_PRESSEDとMOUSE_RELEASEDの2つのイベントの組合せから発生させたイベントであるため、MOUSE_CLICKEDだけを握りつぶしても、MOUSE_PRESSEDとMOUSE_RELEASEDが握りつぶされないからかと推測します。