JDK8u40 で追加された Spinner と Dialog を試してみた。
このエントリーで Arrow button をマウスクリックして操作した場合、呼び出す Dialog を Modality.APPLICATION_MODAL または Modality.WINDOW_MODAL に設定すると
Spinner のインクリメントもしくはデクリメントが止まらないという不思議な現象に悩まされました。
キーボードのカーソルキーでの操作では期待通りに正常に動きます。
なんでマウスで Arrow button をクリックして操作するといけないのか?
MousePressed がブロックされずに押しっぱなし状態で SpinnerBehavior クラスの startSpinning(boolean increment) の Timeline が動いちゃってるようです。
そこで、愚かなアイディアですが MouseReleased が発生してから Dialog を呼び出しちゃえってやってみたら期待通りに動いてくれました。
ごめんなさい。こんな方法しか思いつきませんでした。
spinner.valueProperty().addListener((ov, oldValue, newValue) -> {
System.out.println(newValue);
spinner.setOnMouseReleased(e -> {
if (newValue <= 30_000 && poor.getValue()) {
poor.setValue(Boolean.FALSE);
showPoorDialog();
}
if (newValue >= 70_000 && rich.getValue()) {
rich.setValue(Boolean.FALSE);
showRichDialog();
}
});
spinner.setOnKeyReleased(e -> {
if (newValue <= 30_000 && poor.getValue()) {
poor.setValue(Boolean.FALSE);
showPoorDialog();
}
if (newValue >= 70_000 && rich.getValue()) {
rich.setValue(Boolean.FALSE);
showRichDialog();
}
});
});
と言うことでお終いです。
これってやっぱりバグなんだろうか?
追記:Jose Pereda さんよりコメントをいただきました。
それによると SpinnerSkin class に問題があるようです。
詳しくは Jose さんのコメントをご覧ください。
あわせてこの問題に対する素晴らしい解決方法を提示してくれましたのでエントリー本文にも記載させていただきます。
素晴らしいコードをありがとうございました。
private SpinnerBehavior beh;
@Override
public void initialize(URL url, ResourceBundle rb) {
spinner.valueProperty().addListener((ov, oldValue, newValue) -> {
System.out.println(newValue);
if (beh == null) {
beh = (SpinnerBehavior) ((SpinnerSkin) (spinner.getSkin())).getBehavior();
spinner.focusedProperty().addListener((obs, b, b1) -> {
if (b && !b1) {
beh.stopSpinning();
}
});
}
if (newValue <= 30_000 && poor.getValue()) {
poor.setValue(Boolean.FALSE);
showPoorDialog();
}
if (newValue >= 70_000 && rich.getValue()) {
rich.setValue(Boolean.FALSE);
showRichDialog();
}
});
}