JComboBox는 JComponent 클래스의 하위 클래스로, 텍스트 입력 필드와 드롭다운 목록을 하나로 결합한 컴포넌트입니다. 사용자는 이 드롭다운 목록에서 원하는 값을 선택할 수 있으며, 콤보 박스에서 사용자의 동작이 발생하면 ActionListener, ChangeListener, ItemListener 인터페이스가 이벤트로 발생합니다.
JComboBox 클래스를 상속하여 커스터마이징된 AutoCompleteComboBox를 만들면, 사용자가 키보드로 값을 입력하는 순간 자동으로 일치하는 항목을 찾아 완성해 주는 자동 완성 JComboBox를 구현할 수 있습니다.
구현 예제 코드
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
public class AutoCompleteComboBoxTest extends JFrame {
private JComboBox comboBox;
public AutoCompleteComboBoxTest() {
setTitle("AutoCompleteComboBox");
String[] countries = new String[] {"india", "australia", "newzealand", "england", "germany",
"france", "ireland", "southafrica", "bangladesh", "holland", "america"};
comboBox = new AutoCompleteComboBox(countries);
add(comboBox, BorderLayout.NORTH);
setSize(400, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String []args) {
new AutoCompleteComboBoxTest();
}
}
// AutoCompleteComboBox 구현부
class AutoCompleteComboBox extends JComboBox {
public int caretPos = 0;
public JTextField tfield = null;
public AutoCompleteComboBox(final Object countries[]) {
super(countries);
setEditor(new BasicComboBoxEditor());
setEditable(true);
}
public void setSelectedIndex(int index) {
super.setSelectedIndex(index);
tfield.setText(getItemAt(index).toString());
tfield.setSelectionEnd(caretPos + tfield.getText().length());
tfield.moveCaretPosition(caretPos);
}
public void setEditor(ComboBoxEditor editor) {
super.setEditor(editor);
if(editor.getEditorComponent() instanceof JTextField) {
tfield = (JTextField) editor.getEditorComponent();
tfield.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
char key = ke.getKeyChar();
if (!(Character.isLetterOrDigit(key) || Character.isSpaceChar(key))) return;
caretPos = tfield.getCaretPosition();
String text = "";
try {
text = tfield.getText(0, caretPos);
} catch (javax.swing.text.BadLocationException e) {
e.printStackTrace();
}
for (int i = 0; i < getItemCount(); i++) {
String element = (String) getItemAt(i);
if (element.startsWith(text)) {
setSelectedIndex(i);
return;
}
}
}
});
}
}
}코드 동작 원리
위 코드의 핵심 로직은 다음과 같습니다.
- 편집 가능 설정: 생성자에서
setEditable(true)와BasicComboBoxEditor를 설정하여 콤보 박스에 직접 텍스트를 입력할 수 있도록 합니다. - 키 이벤트 처리: 에디터 컴포넌트인 JTextField에 KeyListener를 등록하고, 문자나 숫자가 입력될 때마다 현재 캐럿 위치까지의 텍스트를 추출합니다.
- 항목 매칭: 콤보 박스의 모든 항목을 순회하며 입력된 텍스트로 시작하는(
startsWith) 항목을 찾으면 해당 항목을 선택합니다. - 캐럿 위치 유지:
setSelectedIndex()를 오버라이드하여 자동 완성된 나머지 부분은 선택(하이라이트) 처리하고, 캐럿은 사용자가 입력 중인 위치에 그대로 유지합니다. 덕분에 계속 타이핑해도 입력 내용이 덮어써지지 않습니다.
실행 결과
프로그램을 실행하고 'a'를 입력하면 'australia' 또는 'america'가 자동으로 제안되고, 이어서 'u'를 입력하면 'australia'로 자동 완성됩니다. 이처럼 사용자가 전체 단어를 입력하지 않아도 일치하는 항목이 즉시 선택되어 편리하게 검색할 수 있습니다.