Swing/InputVerifierFocusOrder のバックアップ(No.9)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/InputVerifierFocusOrder へ行く。
- category: swing folder: InputVerifierFocusOrder title: InputVerifierを設定したコンポーネントのフォーカスナビゲーションをテストする tags: [JTextField, InputVerifier, FocusTraversalPolicy, FocusListener] author: aterai pubdate: 2016-08-15T02:09:37+09:00 description: InputVerifierを設定したコンポーネントの入力の検証とフォーカス移動イベントの順番をテストします。 image: https://drive.google.com/uc?id=19ojUQl6rF4StwHNdQO_xPRlqnkOognwULw
概要
InputVerifier
を設定したコンポーネントの入力の検証とフォーカス移動イベントの順番をテストします。
Screenshot
Advertisement
サンプルコード
JTextField textField = new JTextField(24);
textField.setInputVerifier(new InputVerifier() {
@Override public boolean verify(JComponent c) {
if (c instanceof JTextComponent) {
JTextComponent tc = (JTextComponent) c;
String str = tc.getText().trim();
return !str.isEmpty() && MAX_LEN - str.length() >= 0;
}
return false;
}
@Override public boolean shouldYieldFocus(JComponent input) {
System.out.println("shouldYieldFocus");
if (isAllValid()) {
button.setEnabled(true);
// EventQueue.invokeLater(() -> button.requestFocusInWindow());
} else {
button.setEnabled(false);
}
return super.shouldYieldFocus(input);
}
});
setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() {
@Override public Component getComponentAfter(
Container focusCycleRoot, Component aComponent) {
System.out.println("getComponentAfter");
button.setEnabled(isAllValid());
return super.getComponentAfter(focusCycleRoot, aComponent);
}
@Override public Component getComponentBefore(
Container focusCycleRoot, Component aComponent) {
System.out.println("getComponentAfter");
button.setEnabled(isAllValid());
return super.getComponentBefore(focusCycleRoot, aComponent);
}
});
setFocusCycleRoot(true);
View in GitHub: Java, Kotlin解説
上記のサンプルでは、パネル内のJTextField
がすべて入力検証に成功した場合、JButton
をクリック可能に更新するUI
のテストを行っています。
- Tabキーを押してフォーカス移動するとき、すべての
JTextField
がすべて入力検証に成功する場合は、JButton
をクリック可能に更新し、JButton
にフォーカスを移動し、すぐにSpaceキーなどでクリックしたい InputVerifier#shouldYieldFocus(...)
やFocusListener#focusLost(...)
で、JButton#setEnabled(true)
としても、フォーカスはJButton
に移動しない(初めてJButton
がクリック可能になったときは、先頭のJCheckBox
にフォーカスが移動する)- これらの実行より先に
LayoutFocusTraversalPolicy#getComponentAfter(...)
で、次にフォーカスが移動するコンポーネントが決定されるため、この時点でJButton#setEnabled(true)
になっていないJButton
はスキップされる
- これらの実行より先に
- 回避方法:
InputVerifier#shouldYieldFocus(...)
やFocusListener#focusLost(...)
内でEventQueue.invokeLater(() -> button.requestFocusInWindow() );
などを実行し、一番後でフォーカスを強制的にJButton
に移動する- または、
LayoutFocusTraversalPolicy#getComponentAfter(...)
をオーバーライドして、事前にJButton#setEnabled(true)
を実行する