---
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
---
* Summary [#summary]
`InputVerifier`を設定したコンポーネントの入力の検証とフォーカス移動イベントの順番をテストします。
#download(https://drive.google.com/uc?id=19ojUQl6rF4StwHNdQO_xPRlqnkOognwULw)
* Source Code Examples [#sourcecode]
#code(link){{
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);
}}
* Description [#explanation]
* Description [#description]
上記のサンプルでは、パネル内の`JTextField`がすべて入力検証に成功した場合、`JButton`をクリック可能に更新する`UI`のテストを行っています。
- KBD{Tab}キーを押してフォーカス移動するときすべての`JTextField`がすべて入力検証に成功する場合は、`JButton`をクリック可能に更新、`JButton`にフォーカスを移動、直後にKBD{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)`を実行する
* Reference [#reference]
- [https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/InputVerifier.html#shouldYieldFocus-javax.swing.JComponent- InputVerifier#shouldYieldFocus(JComponent) (Java Platform SE 8)]
* Comment [#comment]
#comment
#comment