0

Series Java Swing Bài 18: JTabbedPane - Thiết kế giao diện đa tab

Khi ứng dụng của bạn ngày càng phình to với hàng chục tính năng (như Quản lý nhân viên, Quản lý sản phẩm, Báo cáo doanh thu), bạn không thể nhồi nhét tất cả vào một màn hình duy nhất. CardLayout (đã học ở Bài 9) là một giải pháp, nhưng nó đòi hỏi bạn phải tự code một thanh menu bên ngoài.

Giải pháp "mì ăn liền" và chuẩn mực nhất của Swing chính là JTabbedPane: Nó cung cấp sẵn một khung giao diện với các "thẻ" (tab) có thể click để chuyển đổi qua lại, y hệt như các tab trên trình duyệt Google Chrome.

1. Khởi tạo và thêm Tab cơ bản

Mỗi Tab trong JTabbedPane thực chất là một ngăn chứa một Component duy nhất. Tuy nhiên, trong thực tế, không ai add một cái JButton đơn độc vào Tab cả. Quy trình chuẩn là:

  1. Tạo một JPanel đóng vai trò là "màn hình" cho Tab đó (sử dụng Layout tùy ý như BorderLayout, GridBagLayout).

  2. Thêm JPanel đó vào JTabbedPane thông qua hàm addTab().

Java

JTabbedPane tabbedPane = new JTabbedPane();

// Màn hình 1
JPanel panelHome = new JPanel();
panelHome.add(new JLabel("Đây là trang chủ"));

// Màn hình 2
JPanel panelSettings = new JPanel();
panelSettings.add(new JLabel("Đây là cài đặt"));

// Thêm các màn hình vào TabbedPane
tabbedPane.addTab("Trang chủ", panelHome);
tabbedPane.addTab("Cài đặt", panelSettings);

2. Các tùy biến mạnh mẽ của JTabbedPane

Thay đổi vị trí của thanh Tab

Mặc định, thanh chứa các nút tab sẽ nằm ở phía TRÊN CÙNG (JTabbedPane.TOP). Tuy nhiên, bạn có thể biến nó thành một Sidebar (thanh bên) bằng cách di chuyển thanh tab sang trái, phải hoặc xuống đáy.

Java

// Thanh tab nằm bên trái (Giống các phần mềm thiết kế / IDE)
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.LEFT);

// Các hằng số khác: TOP, BOTTOM, RIGHT

Thêm Icon và Tooltip (Chú thích khi hover)

Để giao diện bớt khô khan, bạn có thể truyền thêm Icon và Tooltip (đoạn text nhỏ hiện lên khi người dùng để chuột yên trên tab vài giây).

Java

ImageIcon iconUser = new ImageIcon("user.png");

// Hàm addTab đầy đủ: Tiêu đề, Icon, Component (Panel), Tooltip
tabbedPane.addTab("Hồ sơ", iconUser, panelProfile, "Quản lý thông tin cá nhân");

Xóa và vô hiệu hóa Tab

  • removeTabAt(int index): Xóa hẳn một tab khỏi bộ nhớ.

  • setEnabledAt(int index, boolean enabled): Giữ nguyên tab nhưng làm xám nó đi, ngăn người dùng click vào (rất hữu ích khi người dùng chưa có quyền truy cập chức năng đó).

3. Bắt sự kiện chuyển Tab (ChangeListener)

Trong nhiều trường hợp, bạn chỉ muốn query Database để lấy "Báo cáo doanh thu" đúng vào khoảnh khắc người dùng thực sự click vào tab Báo cáo, nhằm tiết kiệm tài nguyên. Bạn cần sử dụng ChangeListener.

Java

tabbedPane.addChangeListener(e -> {
    int selectedIndex = tabbedPane.getSelectedIndex();
    String tabTitle = tabbedPane.getTitleAt(selectedIndex);
    
    System.out.println("Bạn vừa chuyển sang tab số " + selectedIndex + ": " + tabTitle);
    
    // Logic thực tế: Nếu index == 2 thì gọi hàm loadDataFromDatabase()...
});

4. Source Code Thực Chiến: Giao diện Quản trị Đa chức năng

Đoạn mã sau tạo ra một giao diện gồm 3 Tab: Tổng quan, Nhân sự và Cài đặt. Các Tab được bố trí nằm ở bên trái (LEFT) để tạo cảm giác giống một thanh Menu Navigation (Điều hướng) hiện đại.

Java

import javax.swing.*;
import java.awt.*;

public class JTabbedPaneDemo extends JFrame {

    public JTabbedPaneDemo() {
        setTitle("Phần mềm Quản Trị - JTabbedPane");
        setSize(600, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);

        // Khởi tạo JTabbedPane với thanh Tab nằm bên TRÁI
        JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.LEFT);
        
        // Tùy chỉnh font chữ cho thanh Tab
        tabbedPane.setFont(new Font("Arial", Font.BOLD, 14));

        // ==========================================
        // TAB 1: TỔNG QUAN
        // ==========================================
        JPanel tabDashboard = new JPanel(new BorderLayout());
        tabDashboard.setBackground(new Color(236, 240, 241)); // Màu xám nhạt
        JLabel lblDash = new JLabel("Thống kê doanh thu hôm nay", SwingConstants.CENTER);
        lblDash.setFont(new Font("Arial", Font.BOLD, 24));
        tabDashboard.add(lblDash, BorderLayout.CENTER);

        // ==========================================
        // TAB 2: QUẢN LÝ NHÂN SỰ
        // ==========================================
        JPanel tabEmployee = new JPanel(new FlowLayout());
        tabEmployee.setBackground(new Color(253, 235, 208)); // Màu cam nhạt
        tabEmployee.add(new JLabel("Danh sách nhân sự:"));
        tabEmployee.add(new JTextField(20)); // Ô tìm kiếm
        tabEmployee.add(new JButton("Tìm kiếm"));

        // ==========================================
        // TAB 3: CÀI ĐẶT (Được vô hiệu hóa tạm thời)
        // ==========================================
        JPanel tabSettings = new JPanel();
        tabSettings.add(new JLabel("Khu vực cấu hình hệ thống (Cần quyền Admin)"));

        // ==========================================
        // Lắp ghép các Panel vào JTabbedPane
        // ==========================================
        tabbedPane.addTab("Tổng quan", null, tabDashboard, "Xem biểu đồ tổng quan");
        tabbedPane.addTab("Nhân sự", null, tabEmployee, "Quản lý nhân viên");
        tabbedPane.addTab("Cài đặt", null, tabSettings, "Cấu hình hệ thống");

        // Vô hiệu hóa Tab Cài đặt (Index 2)
        tabbedPane.setEnabledAt(2, false);

        // Bắt sự kiện chuyển Tab
        tabbedPane.addChangeListener(e -> {
            int currentTab = tabbedPane.getSelectedIndex();
            System.out.println("Đang thao tác tại Tab Index: " + currentTab);
        });

        // Đưa TabbedPane vào khung chính của cửa sổ
        add(tabbedPane, BorderLayout.CENTER);
    }

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

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í