Java Tutorials - Cách sử dụng Jtable trong Java - How to use tables in Java


Đây là bài dịch từ trang How to use tables của Oracle :http://download.oracle.com/javase/tutorial/uiswing/components/table.html. Bản dịch của congdongjava.com, ghi rõ nguồn khi sao chép bài này .

==============
Java Tutorials - Cách sử dụng Jtable trong Java - How to use tables in Java

Với lớp Jtable các bạn có thể hiển thị dữ liệu với dạng bảng, mặt khác còn cho phép người dùng chỉnh sửa dữ liệu, Jtable không chứ dữ liệu hoặc cache dữ liệu, nó chỉ lại một đơn thuần là một khuôn nhìn dữ liệu của các bạn. Dưới đây là hình minh họa một bảng với việc sử dụng scroll pane.
Tạo một bảng đơn giản

Bảng trong SimpleTableDemo.java khai báo các tên cột dưới dạng một mảng kiểu String (String array)

Dữ liệu trong mảng này được khởi tạo với một mảng đối tượng 2 chiểu (two-dimensional Object array)

Sau đó bảng được xây dựng với dữ liệu của data và tền cột columnNames 

Có 2 hàm khởi tạo của Jtable mà nhận trực tiếp dữ liệu đó là :

Những điểm thuận lợi của 2 hàm khởi tạo trên là chúng được sử dụng một các để dàng, tuy nhiên chúng vận có những khuyết điểm :
- Các ô mặc định được cài đặt là cho phép chỉnh sửa (editable)
- Tất cả các kiểu dữ liệu là giống nhau, tất cả đều được đưa về kiểu chuỗi. Ví dụ, nếu cột trong bảng có kiểu dữ liệu là Boolean, bảng có thể hiển thị dữ liệu trong một hộp kiểm tra (check box). Tuy nhiên, nếu bạn sử dụng một trong hai hàm khởi tạo JTable được liệt kê ở trên, dữ liệu Boolean của bạn được hiển thị như một chuỗi. Bạn có thể thấy sự khác biệt này trong cột Vegetarian của bảng ví dụ trên.
- Yêu cầu các bạn phải đặt tất cả dữ liệu trong một array hoặc một vertor, điều này sẽ không thích hợp trong một số trường hợp. Ví dụ, nếu bạn khởi tạo một tập các đối tượng từ cơ sở dữ liệu, bạn có thể muốn truy vấn các đối tượng trực tiếp cho các giá trị của họ, hơn là sao chép tất cả các giá trị vào một mảng hoặc vector.
--> Để khắc phục được vấn đề này các bạn có thể tham khảo tại "Creating a Table Model", sẽ được đề cặp ở các phần sau.

Dưa bảng vào Container

Đây là một đoạn code đơn giản giúp tạo scroll pane xem như là Container của bảng

Hai đoạn mã trên dùng để làm các công việc sau :
- Hàm khởi tạo của JScrollPane có tham số là bảng, nó sẽ tạo ra một JScrollPane đồng thời tự động thêm bảng vào JScrollPane.
- JTable.setFillsViewportHeight được gọi để thiết lập thuộc tính fillsViewportHeight. Khi giá trị này là TRUE tức là sử dụng toàn bộ chiều cao của container, ngay cả khi bảng không có đủ hàng để sử dụng toàn bộ không gian dọc. và sẽ tạo ra thành cuộn để người dùng có thể để dàng thao tác
Scroll pane tự độn đặt tiêu đề của bảng ở trên cùng, ngay cả khi chúng ta kéo thanh cuộn xuống dưới, tiêu đề của bảng vẫn luôn luôn được nhìn thấy.

Cài đặt và thay đổi độ rộng của cột

Mặc địch, độ rộng của các cột trong jtable là bằng nhau, ngay cả khi có sự tác động của người dùng, thay đỗi độ rộng của các cột, các cột cũng sẽ được thay đổi tương ứng
Để thay đổi độ rộng mặc định của cột, bạn cần sử dụng hàm setPreferredWidth cho từng cột trên bảng của các bạn. Ví dụ thêm đoạn code sau vào SimpleTableDemo để tăng chiểu rộng của cột thứ 3 lơn hơn các cột còn lại.
Sử dụng Selections (cách chọn dữ liệu trên bảng)

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 đó.

Post a Comment

Mới hơn Cũ hơn