web-dev-qa-db-ja.com

JavaFXのEnterを使用したFireButtonのonAction

私はJavaFxの初心者です。私のJavaFXアプリケーションでは、onActionプロパティを設定しましたが、マウスを使用してボタンを押すと正常に機能します。ユーザーがEnterボタンを押しても同じように発射したい。私はそれを行うために偶数ハンドラーを使用できることを知っています。しかし、onAction JavaDocを読むと、このイベントはキーを押すと発生すると言われています。

プロパティの説明:

ボタンが起動されるたびに呼び出されるボタンのアクション。これは、ユーザーがマウスでボタンをクリックしたか、タッチイベント、またはキーを押す、または開発者がプロ​​グラムでfire()メソッドを呼び出したことが原因である可能性があります。

しかし、Enterキーを押しても何も起こりません。ドキュメントにエラーがありますか?ボタンにリスナーを追加せずにそれを達成する他の方法はありますか?

P.S

コメントをスペースキーで確認した後、起動します。しかし、それをEnterキーに設定したいと思います。ボタンがたくさんあります。 button.setDefaultButton(true);を試しましたが、起動されません。ボタンが複数あるからだと思います。ボタンを1つだけ設定すると、問題なく動作します。それを複数のボタンに設定するにはどうすればよいですか?

バインディングを使用して、現在フォーカスされているボタンのデフォルトのボタンプロパティを動的に変更できます

btn.defaultButtonProperty().bind(btn.focusedProperty());
9
Uluk Biy

なぜ私はいつも3歳の質問に答えるのですか...?! ;-)とにかく、誰かがそれが役に立つと思うかもしれません(私を含む)。

Enterキーを押す動作をオーバーライドするには、以下の関数を使用して、シーンのキーを押すイベントフィルターで呼び出します。

public static void overrideEnterKeyPressEvent(KeyEvent evt) {
    EventTarget eventTarget = evt.getTarget();

    if ((eventTarget instanceof TextArea) || (eventTarget instanceof TableView)) {
        return;
    }

    if (eventTarget instanceof Button) {
        Platform.runLater(() -> {
            KeyEvent newEventPressed = new KeyEvent(KeyEvent.KEY_PRESSED, " ", " ", KeyCode.SPACE, false, false, false, false);
            Event.fireEvent(eventTarget, newEventPressed);
            KeyEvent newEventReleased = new KeyEvent(KeyEvent.KEY_RELEASED, " ", " ", KeyCode.SPACE, false, false, false, false);
            Event.fireEvent(eventTarget, newEventReleased);
        });
        evt.consume();
        return;
    }

    Platform.runLater(() -> {
        KeyEvent tabEvent = new KeyEvent(KeyEvent.KEY_PRESSED, "", "\t", KeyCode.TAB, evt.isShiftDown(), false, false, false);
        Event.fireEvent(eventTarget, tabEvent);
    });
    evt.consume();
}

イベントのターゲットに基づいて、関数は次のように機能します。 TextAreaまたはTableViewの場合、これはNoOpです。ボタンの場合、Enterプレスイベントを消費し、スペースキーのプレスイベントとリリースイベントを発生させます。また、他のすべてのコントロールでは、Enterプレスイベントを消費してTabイベントを発生させるため、Enterキーを押すと、Tabと同じようにフォーカスが次のコントロールに移動します。

次に、シーン全体のイベントフィルターを登録するだけです。

    scene.addEventFilter(KeyEvent.KEY_PRESSED, this::onSceneKeyPressedFilter);

そして、イベントフィルターは次のようになります。

private void onSceneKeyPressedFilter(KeyEvent evt) {
    switch (evt.getCode()) {
        case ENTER:
            if (evt.isControlDown() && FxTools.isAncestorNodeTargeted(evt.getTarget(), fxHBoxInputAp)) {
                return; //let the events for the fxHBoxInputAp pane pass through
            }
            overrideEnterKeyPressEvent(evt);
            break;
        ...
        default:
            break;
    }
}

----- isAncestorNodeTargeted()関数を含めるのを忘れたため編集します。コメントありがとう、ロバート-----

public static boolean isDescendantOf(Node node, Node ancestor) {
    while ((node != null) && (node != ancestor)) {
        node = node.getParent();
    }
    return (node != null);
}


public static boolean isAncestorNodeTargeted(EventTarget target, Node ancestor) {
    return (target instanceof Node) ? isDescendantOf((Node) target, ancestor) : false;
}
0
tomorrow

これをプログラム内のすべてのボタンに適用する場合は、JavaFX-Buttonをサブクラス化して、コンストラクターでバインドできます。 fxmlファイルには、カスタムボタンを含める必要があります。

私は次のサブクラスを書きました:

public class FocusedButton extends javafx.scene.control.Button {

    public FocusedButton ( ) {
        super ( );
        bindFocusToDefault ( );
    }

    public FocusedButton ( String text ) {
        super ( text );
        bindFocusToDefault ( );
    }

    public FocusedButton ( String text, Node graphic ) {
        super ( text, graphic );
        bindFocusToDefault ( );
    }

    private void bindFocusToDefault ( ) {
        defaultButtonProperty().bind(focusedProperty());
    }

}

このコードを使用するには、fxmlファイルにカスタムクラスを含める必要があります。

<?import your-package.*?>

シーンビルダーを使用する場合は、少し難しくなります。カスタムボタンをjarファイルにエクスポートし、説明されているようにこれをシーンビルダーに追加する必要があります ここ

0
Qw3ry