0

Series Java Swing Bài 16: JComboBox: Menu thả xuống và cách tích hợp tính năng Auto-complete.

Khi danh sách lựa chọn của bạn có tới 50 tỉnh thành hoặc hàng trăm danh mục sản phẩm, việc dùng JRadioButton hay JCheckBox sẽ khiến giao diện bị "ngập lụt". Đó là lúc JComboBox (Menu thả xuống / Dropdown) tỏa sáng. Nó gói gọn toàn bộ lựa chọn vào một thanh duy nhất và chỉ xổ ra khi người dùng click vào.

1. Khởi tạo cơ bản và lấy dữ liệu

Cách nhanh nhất để tạo một JComboBox là truyền thẳng một mảng tĩnh (Array) chứa các chuỗi vào constructor.

Java

String[] cities = {"Hà Nội", "Hồ Chí Minh", "Đà Nẵng", "Cần Thơ"};
JComboBox<String> cbCities = new JComboBox<>(cities);

// Chọn sẵn một phần tử theo index (ví dụ: Chọn "Hồ Chí Minh" - index 1)
cbCities.setSelectedIndex(1);

Cách lấy dữ liệu khi người dùng chọn:

  • getSelectedItem(): Trả về trực tiếp đối tượng đang được chọn (Thường dùng nhất).

  • getSelectedIndex(): Trả về vị trí (từ 0) của phần tử. Trả về -1 nếu không có gì được chọn.

2. Thao tác dữ liệu động với DefaultComboBoxModel

Trong thực tế làm dự án, danh mục sản phẩm thường được kéo từ Database về (MySQL, PostgreSQL), nên số lượng là biến động. Bạn không thể dùng mảng tĩnh.

Cũng giống như JTable hay JList, JComboBox phân tách rõ ràng giữa phần Giao diện (View) và phần Dữ liệu (Model). Để thêm/sửa/xóa dữ liệu thời gian thực, bạn phải thao tác qua DefaultComboBoxModel.

Java

// 1. Khởi tạo ComboBox rỗng
JComboBox<String> cbProducts = new JComboBox<>();

// 2. Tạo Model để quản lý dữ liệu
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();

// 3. Đổ dữ liệu từ List hoặc Database vào Model
model.addElement("Laptop Dell XPS");
model.addElement("MacBook Pro 14");
model.addElement("Bàn phím cơ Keychron");

// 4. Gắn Model vào ComboBox
cbProducts.setModel(model);

// Xóa dữ liệu
model.removeElement("MacBook Pro 14"); // Xóa theo tên
model.removeAllElements(); // Xóa sạch toàn bộ menu

3. Khả năng Edit (Nhập liệu tự do)

Mặc định, JComboBox chỉ cho phép chọn những gì đã có sẵn trong danh sách. Nhưng nếu bạn muốn người dùng có thể vừa chọn, vừa tự gõ thêm dữ liệu mới (giống thanh địa chỉ của trình duyệt web)?

Bạn chỉ cần một dòng code duy nhất để mở khóa tính năng này:

Java

cbCities.setEditable(true);

Lúc này, phần ô hiển thị của JComboBox sẽ biến thành một JTextField. Nếu người dùng gõ chữ "Nha Trang" (không có trong danh sách gốc) và bấm Enter, hàm cbCities.getSelectedItem() sẽ trả về chuỗi "Nha Trang" đó.

4. Tuyệt chiêu: Tích hợp Auto-complete (Tìm kiếm thông minh)

Java Swing không có sẵn tính năng Auto-complete (tự động gợi ý khi gõ). Tuy nhiên, bằng cách kết hợp tính năng Editable ở trên và sự kiện bàn phím (KeyAdapter), chúng ta có thể tự build một thanh tìm kiếm thông minh y hệt Google Search.

Thuật toán cơ bản:

  1. Lấy ra cái JTextField ẩn bên trong JComboBox.

  2. Lắng nghe sự kiện gõ phím (KeyReleased).

  3. Mỗi khi người dùng gõ một chữ, ta xóa sạch Model hiện tại.

  4. Lọc từ mảng dữ liệu gốc những từ nào chứa chữ vừa gõ, add lại vào Model.

  5. Cố ép Menu thả xuống mở ra (showPopup()) để người dùng thấy kết quả lọc.

5. Source Code Thực Chiến: ComboBox Cơ Bản & Auto-complete

Đoạn code dưới đây thiết kế một giao diện gồm 2 phần: Phía trên là ComboBox tĩnh, phía dưới là một ComboBox Auto-complete hoạt động cực kỳ mượt mà.

Java

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;

public class JComboBoxDemo extends JFrame {

    public JComboBoxDemo() {
        setTitle("Khám phá JComboBox & AutoComplete");
        setSize(450, 250);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setLayout(new FlowLayout(FlowLayout.CENTER, 20, 20));

        // ==========================================
        // 1. JCOMBOBOX CƠ BẢN (TĨNH)
        // ==========================================
        JPanel panelBasic = new JPanel(new BorderLayout(5, 5));
        panelBasic.add(new JLabel("Chọn vai trò:"), BorderLayout.NORTH);

        String[] roles = {"Giám đốc", "Quản lý", "Nhân viên IT", "Kế toán"};
        JComboBox<String> cbRoles = new JComboBox<>(roles);
        
        // Bắt sự kiện ngay khi người dùng chọn mục khác
        cbRoles.addActionListener(e -> {
            String selected = (String) cbRoles.getSelectedItem();
            System.out.println("Bạn vừa chọn: " + selected);
        });
        
        panelBasic.add(cbRoles, BorderLayout.CENTER);

        // ==========================================
        // 2. JCOMBOBOX AUTO-COMPLETE (TÌM KIẾM)
        // ==========================================
        JPanel panelSearch = new JPanel(new BorderLayout(5, 5));
        panelSearch.add(new JLabel("Tìm kiếm ngôn ngữ (Gõ 'J' hoặc 'P'):"), BorderLayout.NORTH);

        // Danh sách dữ liệu gốc (Thường load từ Database)
        String[] languages = {"Java", "JavaScript", "Python", "PHP", "C++", "C#", "Ruby", "Swift", "Go"};
        
        JComboBox<String> cbSearch = new JComboBox<>(languages);
        cbSearch.setEditable(true); // BẬT TÍNH NĂNG NHẬP LIỆU
        cbSearch.setPreferredSize(new Dimension(200, 30));

        // Lấy JTextField ẩn bên trong JComboBox để bắt sự kiện gõ phím
        JTextField textEditor = (JTextField) cbSearch.getEditor().getEditorComponent();

        textEditor.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                // Bỏ qua các phím điều hướng (Lên, Xuống, Trái, Phải, Enter) để không làm hỏng menu
                if (e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN 
                    || e.getKeyCode() == KeyEvent.VK_ENTER) {
                    return;
                }

                SwingUtilities.invokeLater(() -> {
                    String input = textEditor.getText().toLowerCase();
                    
                    // Xóa menu cũ
                    DefaultComboBoxModel<String> model = (DefaultComboBoxModel<String>) cbSearch.getModel();
                    model.removeAllElements();

                    // Tìm và thêm các từ khớp với input
                    boolean hasResult = false;
                    for (String item : languages) {
                        if (item.toLowerCase().contains(input)) {
                            model.addElement(item);
                            hasResult = true;
                        }
                    }

                    // Trả lại đoạn text người dùng đang gõ dở vào ô nhập (Vì thao tác xóa model làm mất chữ)
                    textEditor.setText(input);
                    
                    // Hiển thị Popup nếu có kết quả
                    if (hasResult && !input.isEmpty()) {
                        cbSearch.showPopup();
                    } else {
                        cbSearch.hidePopup();
                    }
                });
            }
        });

        panelSearch.add(cbSearch, BorderLayout.CENTER);

        // Thêm vào JFrame
        add(panelBasic);
        add(panelSearch);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new JComboBoxDemo().setVisible(true));
    }
}

Hãy copy chạy code, click vào ô "Tìm kiếm ngôn ngữ" và gõ thử chữ "p" (không viết hoa). Bạn sẽ thấy Menu lập tức xổ xuống và chỉ hiển thị "Python", "PHP", hoạt động giống hệt một ô tìm kiếm chuyên nghiệp.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí