InputVerifierを設定したコンポーネントのフォーカスナビゲーションをテストする
Total: 4263
, Today: 2
, Yesterday: 0
Posted by aterai at
Last-modified:
概要
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)
を実行する