JTable trong Java:Cách sử dụng cơ bản

Trong Java, JTable là một trong những component chủ đạo trong việc hiển thị dữ liệu. Nó là một Swing component cung cấp khả năng biểu diễn dữ liệu ở dạng bảng biểu. Ngoài ra, JTable còn cho phép bạn có thể dễ dàng chỉnh sửa thông tin ngay trên các cell của nó như khi bạn làm việc với Excel vậy. Trong bài viết này, chúng ta sẽ cùng tìm hiểu cách thao tác với dữ liệu của bảng để hiển thị chúng lên JTable.

Như các bạn đã biết, kiến trúc của JTable nói riêng và Swing nói chung, đều được xây dựng dựa theo mô hình MVC nên phần data (Model) sẽ tách biệt với phần giao diện (UI). Điều này tạo nên sự rõ ràng, mạch lạc cho code, nhưng có thể gây khó khăn với những ai mới bắt đầu.

Để hiển thị dữ liệu với JTable, chúng ta có nhiều cách. Bạn có thể lợi dụng một contructor của JTable như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class MyTable extends javax.swing.JFrame {
    public final static boolean GENDER_MALE = true;
    public final static boolean GENDER_FEMALE = false;
    public final static String[] columnNames = {
        "First Name", "Last Name", "Date of Birth", "Account Balance", "Gender"
    };
    public Object[][] values = {
        {
            "Clay", "Ashworth",
            new GregorianCalendar(1962, Calendar.FEBRUARY, 20).getTime(),
            new Float(12345.67), GENDER_MALE}, {
            "Jacob", "Ashworth",
            new GregorianCalendar(1987, Calendar.JANUARY, 6).getTime(),
            new Float(23456.78), GENDER_MALE}, {
            "Jordan", "Ashworth",
            new GregorianCalendar(1989, Calendar.AUGUST, 31).getTime(),
            new Float(34567.89), GENDER_FEMALE}, {
            "Evelyn", "Kirk",
            new GregorianCalendar(1945, Calendar.JANUARY, 16).getTime(),
            new Float(-456.70), GENDER_FEMALE}, {
            "Belle", "Spyres",
            new GregorianCalendar(1907, Calendar.AUGUST, 2).getTime(),
            new Float(567.00), GENDER_FEMALE}
    };
    /** Creates new form MyTable */
    public MyTable() {
        initComponents();
        setLayout(new BorderLayout());
        JTable myTable = new JTable(values, columnNames);
        JScrollPane jsp = new JScrollPane(myTable);
        getContentPane().add(jsp, BorderLayout.CENTER);
    }

Bạn cũng lưu ý rằng, để JTable có thể hiển thị tên cột, các bạn cần bao nó lại bằng một JScrollPane.

Cách trên giúp bạn nhanh chóng tạo ra một JTable với dữ liệu được hiển thị. Mảng 1 chiều cung cấp tên cột, mảng 2 chiều cung cấp data cho bảng. Tuy nhiên, cách này không thực tế, chúng ta thường chỉ sử dụng nó trong demo, khi bạn mới học về JavaSE. Một cách khác mà mình sẽ giới thiệu cho các bạn, cách mà các bạn sẽ thường dùng trong bài tập lớn, project…, đó là sử dụng data model.

Data model đảm nhận nhiệm vụ cung cấp dữ liệu hiển thị cho JTable. Sử dụng data model giúp ứng dụng “MVC” hơn bằng việc tách riêng phần data và phần UI, tạo ra sự custom tốt hơn cho những bài toán phức tạp.

Về cơ bản, một data model được cài đặt 9 phương thức do interface TableModel định nghĩa. Các phương thức đó được liệt kê trong hình dưới đây:

table model method JTable trong Java: Cách sử dụng cơ bản

Tác dụng của những phương thức trên bạn có thể dễ dàng suy ra thông qua tên của chúng, mình không nói lại nữa nhé. Bạn cũng có thể tham khảo thêm trên Java docs. Bạn sẽ phải tự mình cài đặt cả 9 phương thức trong trường hợp bạn tạo ra data model bằng cách implements interface TableModel. Tuy nhiên Java cũng tạo ra một số các lớp khác được cài đặt sẵn một số phương thức, giúp cho công việc của chúng ta đơn giản hơn. Cụ thể như class DefaultTableModel và abstract class AbstractTableModel, tất cả đều implements interface TableModel. Thông thường, chúng ta sẽ tạo ra data model bằng cách kế thừa AbstractTableModel. Khi đó, chúng ta chỉ cần thiết phải override lại 4 phương thức.

Dưới đây, mình sẽ tạo ra lớp CustomTableModel như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class CustomTableModel extends AbstractTableModel {
    public final static boolean GENDER_MALE = true;
    public final static boolean GENDER_FEMALE = false;
    public final static String[] columnNames = {
        "First Name", "Last Name", "Date of Birth", "Account Balance", "Gender"
    };
    public Object[][] values = {
        {
            "Clay", "Ashworth",
            new GregorianCalendar(1962, Calendar.FEBRUARY, 20).getTime(),
            new Float(12345.67), GENDER_MALE}, {
            "Jacob", "Ashworth",
            new GregorianCalendar(1987, Calendar.JANUARY, 6).getTime(),
            new Float(23456.78), GENDER_MALE}, {
            "Jordan", "Ashworth",
            new GregorianCalendar(1989, Calendar.AUGUST, 31).getTime(),
            new Float(34567.89), GENDER_FEMALE}, {
            "Evelyn", "Kirk",
            new GregorianCalendar(1945, Calendar.JANUARY, 16).getTime(),
            new Float(-456.70), GENDER_FEMALE}, {
            "Belle", "Spyres",
            new GregorianCalendar(1907, Calendar.AUGUST, 2).getTime(),
            new Float(567.00), GENDER_FEMALE}
    };
    @Override
    public int getRowCount() {
        return values.length;
    }
    @Override
    public int getColumnCount() {
        return columnNames.length;
    }
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return values[rowIndex][columnIndex];
    }
    // Need for showing column name
    @Override
    public String getColumnName(int columnIndex) {
        return columnNames[columnIndex];
    }
}

Trong thực tế, dữ liệu của bảng thường được cung cấp dưới dạng Vector hoặc List thay vì mảng 2 chiều như demo này. Khi đó, bạn cần sửa lại những phương thức đã override cho phù hợp.

Để JTable của chúng ta sử dụng data model vừa được tạo ra, chúng ta có thể sử dụng phương thức setModel() của JTable:

1
myTable.setModel(new CustomTableModel());

Kết quả khi chạy chương trình:

demo jtable basic JTable trong Java: Cách sử dụng cơ bản

Nhìn từ bề nổi, bạn có thể nhận xét rằng cấu trúc của 2 lớp này chỉ khác nhau ở chỗ DefaultTableModel được cài đặt nốt 3 phương thức mà AbstractTableModel còn bỏ ngỏ. Thế nhưng còn có sự khác biệt khá lớn nữa, để AbstractTableModel được khuyến khích sử dụng, chứ không phải DefaultTableModel.

Sở dĩ như vậy là bởi vì AbstractTableModel cho phép chúng ta toàn quyền điều khiển dữ liệu input cũng như output. Để xuất dữ liệu ra bảng, chúng ta phải tự mình cài đặt phương thức getValueAt(). Phương thức này nhận 2 tham số là chỉ số cột và chỉ số dòng. Nó quy định dữ liệu gì sẽ được cung cấp cho mỗi ô trong bảng (được xác định bởi 2 tham số hình thức). Không giống như thế, DefaultTableModel thiếu tính mềm dẻo và mở rộng hơn nhiều. Mặc định nó được cài sẵn tất cả các phương thức mà đã implements từ TableModel. Điều này dẫn đến việc bạn sẽ khó khăn hơn khi muốn can thiệp vào quá trình xử lý bảng. Hơn nữa, DefaultTableModel sử dụng Vector (chính xác hơn là một Vector bao gồm những Vector khác) làm dữ liệu input. Và kéo theo đó, các phương thức như getValueAt()setValueAt()… trong quá trình thực thi cũng thao tác với dữ liệu dạng Vector này. Vector là một Collection đã “lỗi thời” xuất hiện từ thời Java 1.0. Bạn có thể thấy trong Netbeans, bạn sẽ nhận được thông báo “Obsolete Collection” nếu cố tình dùng Vector. Vector có khá nhiều hạn chế như less thread-safe và chậm chạp hơn so với các Collection khác. ArrayList được khuyến cáo thay thế cho Vector. Cụ thể mình sẽ có một bài viết khác về vấn đề này.

Vậy nên, nếu làm việc với data model, bạn nên sử dụng AbstractTableModel và sử dụng ArrayList cho dữ liệu đầu vào.

Trong bài viết này, mình đã hướng dẫn cho các bạn cơ bản về cách hiển thị dữ liệu với JTable. Ở vài viết tiếp theo, chúng ta vẫn sẽ xoay quanh data model. Mình sẽ hướng dẫn các bạn override một số phương thức của TableModel để có thể chỉnh sửa dữ liệu trực tiếp trên các ô của bảng và làm thế nào để xử lý kết quả người dùng vừa mới cập nhật đó.

Happy Coding! 40 JTable trong Java: Cách sử dụng cơ bản

Download source code của bài viết

codeimba.com

Advertisements

Posted on November 5, 2012, in GUI in Java, Java. Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: