質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

Q&A

解決済

1回答

3419閲覧

JavaFX8 ダイアログ表示でのESCキーイベントの処理

silver

総合スコア17

JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

0グッド

0クリップ

投稿2015/11/21 09:24

編集2015/11/23 05:56

JavaFX8に興味を持って勉強を始めたばかりの初心者です。
どうかご教授よろしくお願いします。

Windows10で作成、実行しています。
JavaFX8で作成した画面に「キャンセル」ボタンを設けて、「キャンセル」をクリック、または「ESC」キーを押したら画面を終了する処理を作成しました。
※「キャンセル」ボタンは、cancelButtonに設定しており、ActionEventを設定しています。

ただ、キャンセルが押された場合、まずは、確認ダイアログ(Alertクラス)を表示して、確認ダイアログで「OK」が選択されてから終了したいと考えています。

質問内容ですが、
「ESC」キーを押した場合の処理がわかりません。
画面で「ESC」キーを押すと、ActionEventで受け取るのですが、キーイベントがそのまま確認ダイアログにも渡されてしまっているようです。
その為、一瞬だけ確認ダイアログが表示され、結果としてキャンセルが戻ってきてしまいます。

希望としては、「ESC」キーを押したイベントが警告ダイアログに渡らないようにしたいのですが、何か方法はありますでしょうか?

画面のコントローラークラスのソースです。

public class FXMLDocumentController implements Initializable { @FXML private void handleButtonAction(ActionEvent event) { Alert alert = new Alert(Alert.AlertType.CONFIRMATION); alert.setTitle("確認"); alert.setHeaderText("ヘッダー情報"); alert.setContentText("コンテンツ情報"); Optional<ButtonType> result = alert.showAndWait(); if(ButtonType.OK.equals(result.get())){ Platform.exit(); } } @Override public void initialize(URL url, ResourceBundle rb) { // TODO } }

よろしくお願いします。

追記です。)
ただ、キャンセルが押された場合、まずは、確認ダイアログ(Alertクラス)を表示して、確認ダイアログで「OK」が選択されてから終了したいと考えています。

ではなく

ただ、キャンセルが押された場合__(ESCキーが押された場合も)__、まずは、確認ダイアログ(Alertクラス)を表示して、確認ダイアログで「OK」が選択されてから終了したいと考えています。

fxmlは下記になってます。

<?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="dialogsample.FXMLDocumentController"> <children> <Button cancelButton="true" layoutX="126" layoutY="90" onAction="#handleButtonAction" text="CANCEL" /> </children> </AnchorPane>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

argius

2015/11/22 11:55

ESCキーイベントの処理はどうやっているのですか?
silver

2015/11/23 05:43

ありがとうございます。 ESCキーに対するKeyEventの処理は特にしておりません。 ButtonをcancelButtonに設定すれば、ESCキーを押した場合は、ActionEventが発生するという認識でいますが、そもそもそこが間違えているのでしょうか? AlertクラスにあるキャンセルボタンもcancelButtonに設定されているので、そのままActionEventが伝播されていると思っていました。 よろしくお願いします。
argius

2015/11/23 06:29

情報の追記、ありがとうございます。問題の意味が分かりました。少し調べてみましたが、一筋縄では行かないようですね。
silver

2015/11/23 07:24

説明足りなく申し訳ありませんでした。やはり難しいのですかね。
guest

回答1

0

ベストアンサー

(追記)

eripongさんにいただいたコメントによれば、下記のバグによる挙動みたいです。
詳しくは、この回答のコメント欄を参照して下さい。

[JDK-8131151] Pressing ESC in a nested alert closes self and parent alert - Java Bug System
https://bugs.openjdk.java.net/browse/JDK-8131151

そうなると、AlertダイアログのOnKeyReleasedイベントでESCキーを無効にする方がバグの回避方法としては正しいですね。

lang

1alert.getDialogPane().setOnKeyReleased(new EventHandler<KeyEvent>() { 2 public void handle(KeyEvent e) { 3 if (e.getCode() == KeyCode.ESCAPE) { 4 e.consume(); 5 } 6 } 7});

(最初の回答)

根本的な解決ではないのですが、下記のコードを追加すればそれらしい動作にできそうです。

実際は、ESCキーでダイアログを開いた時に即時にダイアログが閉じています。
その直後に、ESCキーのイベント処理で、もう一度handleButtonActionを直接呼び出しています。確実ではありませんが、Platform.runLaterで呼び出すことで、即時にダイアログが閉じることによるちらつきを見えにくくしています。

lang

1scene.setOnKeyPressed(new EventHandler<KeyEvent>() { 2 public void handle(KeyEvent e) { 3 if (e.getCode() == KeyCode.ESCAPE) { 4 Platform.runLater(() -> handleButtonAction(new ActionEvent())); 5 } 6 } 7});

投稿2015/11/23 08:31

編集2015/11/23 14:35
argius

総合スコア9390

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

silver

2015/11/23 09:24

なるほどですね。ありがとうございます。 動きとしては、希望通りの動きしました。 大変助かりました。 argiusさんの言う通り、根本ではないですがとりあえず回避策はできました。 もう少し自分でも調べてみます。
argius

2015/11/23 10:46

私のJavaバージョンが少し古かったので、8u66にバージョンアップして確認しましたが、変わりませんでした。 特におかしなことも特殊なことをしているわけでもないと思うので、この挙動は納得いきませんね。 Alertは比較的新しいクラスなので、バグの可能性もあるかも知れません。
silver

2015/11/23 13:26

本当にありがとうございます。 Alertが使えるようになったとのことで楽になるから使ってみたのですが・・・ 大変勉強になりました。 いろいろググってみたのですがこの辺の事を突っ込んでいるものがなかったので 本当に助かりました。
argius

2015/11/23 13:38 編集

Alertは情報がまだ少ないですね。 それでもダイアログが使えるようになったのは嬉しいですよね。 というか、なぜ今までなかったのかは本当に不思議でなりません。 Swingを置き換えるものにしては変なところで不足してるんですよね、FXは。 ともあれ、ちゃんとした解決でなくて恐縮ですが、お役に立てたようで良かったです。
eripong

2015/11/23 14:07

> the context menu code was listening for the ESCAPE key on key _pressed_, > and the dialog code was listening for the escape key on key _released_. > So, even though the event was being properly consumed in the context > menu code, the dialog was watching for (and receiving) an entirely > different event. コンテキストメニューではキーが押された際(所謂KeyPressedEvent)に処理するのに、 ダイアログではキーが離された際(所謂KeyReleasedEvent)に処理することによる、 と書かれている様で、それらしいのですが。
argius

2015/11/23 14:30

eripongさん コメントありがとうございます。 どうやらそのバグにまちがい無いようです。 回答欄に追記させていただきます!
eripong

2015/11/23 14:39

お、該当しましたか。 良かったです。
argius

2015/11/23 14:43

eripongさん はい、自力で見つけられなかったので助かりました。 ありがとうございました!
silver

2015/11/24 08:35

コメントありがとうございます。 バグなんですね・・・ ありがとうございました。
silver

2015/11/24 08:51

試してみました!ジャストフィットですね。 eripongさん、argiusさん 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問