JComboBoxへのフォーカス移動がInputVerifierの検証で拒否されたらドロップダウンリスト表示をキャンセルする
Total: 1555, Today: 3, Yesterday: 3
Posted by aterai at
Last-modified:
Summary
JComboBoxへのマウスクリックによるフォーカス移動が別コンポーネントに設定されているInputVerifierの検証で拒否された場合、そのドロップダウンリストの表示をキャンセルします。
Screenshot

Advertisement
Source Code Examples
class BasicComboPopup2 extends BasicComboPopup {
private transient MouseListener handler2;
@Override public void uninstallingUI() {
super.uninstallingUI();
handler2 = null;
}
// Java 9: protected BasicComboPopup2(JComboBox<Object> combo) {
protected BasicComboPopup2(JComboBox<?> combo) {
super(combo);
}
@Override protected MouseListener createMouseListener() {
if (Objects.isNull(handler2)) {
handler2 = new Handler2();
}
return handler2;
}
private class Handler2 extends MouseAdapter {
@Override public void mousePressed(MouseEvent e) {
if (!SwingUtilities.isLeftMouseButton(e) || !comboBox.isEnabled()) {
return;
}
boolean hasFocus = true;
if (comboBox.isEditable()) {
Component comp = comboBox.getEditor().getEditorComponent();
if (!(comp instanceof JComponent) || ((JComponent) comp).isRequestFocusEnabled()) {
hasFocus = comp.hasFocus() || comp.requestFocusInWindow();
}
} else if (comboBox.isRequestFocusEnabled()) {
hasFocus = comboBox.hasFocus() || comboBox.requestFocusInWindow();
}
Component c = e.getComponent();
if (!hasFocus && c instanceof AbstractButton) {
((AbstractButton) c).getModel().setPressed(false);
}
if (hasFocus) {
togglePopup();
}
}
@Override public void mouseReleased(MouseEvent e) {
Component source = (Component) e.getSource();
Dimension size = source.getSize();
Rectangle bounds = new Rectangle(0, 0, size.width - 1, size.height - 1);
if (!bounds.contains(e.getPoint())) {
MouseEvent newEvent = SwingUtilities.convertMouseEvent(e.getComponent(), e, list);
Point location = newEvent.getPoint();
Rectangle r = new Rectangle();
list.computeVisibleRect(r);
if (r.contains(location)) {
if (comboBox.getSelectedIndex() == list.getSelectedIndex()) {
comboBox.getEditor().setItem(list.getSelectedValue());
}
comboBox.setSelectedIndex(list.getSelectedIndex());
}
comboBox.setPopupVisible(false);
}
hasEntered = false;
stopAutoScrolling();
}
}
}
View in GitHub: Java, KotlinDescription
InputVerifierJTextFieldに少なくとも5文字以上の入力が必要なInputVerifierを設定5文字以下の場合は他のコンポーネントへのフォーカス移動が不可となる
DefaultDefaultの編集不可JComboBoxはInputVerifierでフォーカス移動が拒否されていてもクリックするとドロップダウンリストが表示される
setFocusable(false)setFocusable(false)を設定した編集不可JComboBoxはフォーカス移動前のInputVerifierによる検証は実行されないsetFocusable(false)が設定されていてもJComboBoxをクリックしてドロップダウンリストを表示することは可能
setEditable(true)Defaultの編集可JComboBoxはInputVerifierでフォーカス移動が拒否されてもArrowButtonクリックするとドロップダウンリストが表示されるComboBoxEditorがクリックされた場合はフォーカス移動が拒否されるとドロップダウンリスト表示もキャンセルされる
Override BasicComboPopupBasicComboPopupでmousePressedが実行されたときrequestFocus()の戻り値が無視されているので、この戻り値がフォーカス変更要求が確実に失敗する場合(InputVerifierの検証で拒否されるなど)のfalseならBasicComboPopup#togglePopup()を実行しないよう修正ArrowButtonがクリックされた場合はその選択状態描画が残る場合がある?のでドロップダウンリストの表示がキャンセルされた場合はJButton#getModel()#setPressed(false)で選択状態をクリア
Reference
- How to Use the Focus Subsystem (The Java™ Tutorials > Creating a GUI With Swing > Using Other Swing Features)
- java - Prevent a JComboBox popup from appearing. Passing InputVerifier - Stack Overflow
PopupMenuListenerをJComboBoxに設定してInputVerifierでフォーカス移動が拒否されたらドロップダウンリスト表示をキャンセルする方法もある
- JPopupMenuを開く前に対象となるJTextFieldにFocusを移動する
- ComboBoxEditorにJLayerを設定し入力の妥当性を表示する
- [JDK-8285698] Create a test to check the focus stealing of JPopupMenu from JComboBox - Java Bug System