Hướng dẫn sử dụng jTable với AbstractTableModel trong NetBeans. | How to use jTable with AbstractTableModel in NetBeans?

Theo yêu cầu một vị thị giả, nên bài viết này tôi sẽ hướng dẫn sử dụng JTable với lớp AbstractTableModel trên ứng dụng lập trình Netbeans, do này viết theo hiểu biết của bản thân nên có gí sơ xót các bạn chỉnh lý hộ ^^!

AbstractTableModel là gì?

Làm một trong 2 lớp model AbstractTableModel và DefaultTableModel được Java cung cấp nhằm mục đích hỗ trợ trong việc tạo một bảng dữ liệu(JTable) và thao tác nó một cách thuận tiên, nhanh chóng hơn so với cách thông thường là chỉ dùng mỗi JTable.

Về cơ bản 2 lớp này hoàn toàn giống nhau, chỉ là với AbstractTableModel thì bạn có thể thực hiện được nhiều thao tác và nhiều tùy biến hơn, giúp bạn hiển thị, chỉnh sửa, thao tác một cách mền mại hơn so với DefaultTableModel, nhưng bù lại sử dụng nó lại phức tạp hơn so với DefaultTableModel, nói chung cái nào cũng có thế mạnh riêng và nhược điểm riệng.


Một số lưu ý:

Lớp AbstractTableModel này có một số đặc thù nên tôi sẽ mô tả sơ qua về cách sử dụng lớp này nhưng có vẻ hơi khó mô tả ^^! có chỗ nào khó hiểu bạn hãy comment tại đây mình sẽ giải thích lại.

Như trong bài "Netbeans - Hướng dẫn sử dụng jTable với DefaultTableModel" tôi đã hướng dẫn trước đây(nhìn lại thấy còn sơ xài khi nào rãnh viết lại ^^!) bạn thấy rằng ta không cần viết một lớp mới, mà có thể sử dụng khai báo trực tiếp lớp DefaultTableModel.

Nhưng đối với lớp AbstractTableModel thì bạn không thể làm được như thế, mà bắt buộc ta phải xây dựng một lớp mới hoàn toàn và lớp này phải được kế thừa từ lớp AbstractTableModel, từ đây ta sẽ viết lại một lớp Table Model hoàn toàn mới.

public class MyTableModel extends AbstractTableModel

Một điểm cần phải nhớ là trong lớp Table Model mới được tạo và kế thừa từ lớp AbstractTableModel bạn phải thực hiện viết đè(overwritten) lên ít nhất là ba phương thức sau:

public int getRowCount(); // Phương thức trả về số dòng của bảng.
public int getColumnCount(); // Phương thức trả về số cột của bảng.
public Object getValueAt(int row, int column); // Phương thức trả về giá trị của mỗi ô.

Tất nhiên như vậy vẫn là chưa đủ, vì một bảng dữ liệu thì phải có dữ liệu ~^^~, do cấu trúc JTable nên dữ liệu của mỗi ô được xác định bởi dòng(row)cột(column) nên người ta à là lập trình viên thường cấu hình kiểu dữ liệu của bảng là kiểu Object 2 chiều hoặc kiểu List chứa đối tượng Object như sau:

Object[][] DATA;
List<Object[]> DATA = new ArrayList<Object[]>();

Bạn có thể hoàn toàn tùy chọn kiểu dữ liệu của bảng theo ý thích, miễn sao đáp ứng cú pháp và yêu cầu của các phương thức trong Java,  vì tương đối rối nên mình chỉ giới thiệu 2 kiểu dữ liệu để lưu giá trị của bảng chuẩn nhất đang được sử dụng nhiều nhất.

À ném quên còn phần tên cột(name column) nữa, đối với tên cột thì ta thường sử dụng kiểu dữ liệu dạng mảng String(array String) để lưu trữ.

String[] COLUMN_NAMES = {"Col 01", "Col 02", "Col 03"};

Tôi thật sự rất muốn giải thích thêm các thông số khi sử dụng lớp AbstractTableModel nhưng thực nó rất nhiều và tùy theo cách sử dụng thì sẽ có các tùy biến khác nhau, nên dù nuốn tôi cũng không biết trình như thế nào ^^! Nên tiếp sau đây tôi xin hướng dẫn một cách mà tôi thường sử dụng nhất để tạo một bảng JTable bằng lớp AbstractTableMode, đây là cách dễ nhất mà tôi rút ra được trong quá trình làm việc ^^!.


Hướng dẫn

Đầu tiên ta cần tạo một dự án trên Netbeans để thực hành, bạn có thể tham khảo bài viết "NetBeans IDE 7.3.1 - Hướng dẫn tạo dự án mới và một JFRAME" nêu chưa biết cách tạo dự án trên NetBeans.

Tiếp theo ta cần tạo một JFrame mới bằng cách chọn vào gói package của dự án và click chuột phải chọn "New" → "JFrame Form".


Cửa sổ cấu hình tạo "New JFrame Form", ở đây tôi đặt tên "JFrame""jtable_with_model". Chọn "Finish" để kết thúc quá trình tạo new jframe form.


Tiếp theo ta vẽ một jTable từ bảng công cụ của Netbeans như hình bên dưới.


Ta sẽ loại bỏ model table mặc định được tạo khi ta vẽ jTable bằng cách vào mục "Properties" để tìm tới dòng(row) "model" chọn vào nút(botton) "[...]", một cửa sổ cấu hình model sẽ được hiển thị như hình bên dưới.


Trong cửa sổ cấu hình modle bạn chọn button "Reset to Default" để trả jTable về nguyên gốc không có model như hình bên dưới.


Như đã trình bày ở mục trên để sử dụng được AbstractTableModel thì tà cần tạo riêng một class được kế thừa từ lớp AbstractTableModel, vì vậy tôi sẽ tạo một class mới có tên là "myAbstractTableModel" bằng cách click phải chuột vào biểu tương "Packager" của project, tai pop-up menu chọn "New""Java Class"


Trong lớp "myAbstractTableModel.java" vừa được bạn viết vào mã(code) sau:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tablewithabstracttablemodel;

/**
 *
 * @author Admin
 */
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;

public class myAbstractTableModel extends AbstractTableModel {

    private String[] header;
    private ArrayList<Object[]> data;

    // Khi khởi tạo ta sẽ kèm theo tên cột và dữ liệu cho bảng.
    public myAbstractTableModel(String[] header, ArrayList<Object[]> data) {
        this.header = header;
        this.data = data;
    }

    // Ghi đè và viết code
    // cho phương thức lấy thông tin tổng số cột.
    @Override
    public int getColumnCount() {
        return header.length;
    }

    // Ghi đè và viết code
    // cho phương thức lấy tên cột theo chỉ mục 0, 1, 2....
    @Override
    public String getColumnName(int column) {
        return header[column];
    }

    // Ghi đè và viết code
    // cho phương thức lấy thông tin tổng số dòng của bảng.
    @Override
    public int getRowCount() {
        return data.size();
    }

    // Ghi đè và viết code
    // cho phương thức lấy thông tin tổng số dòng của bảng.   
    @Override
    public Object getValueAt(int row, int column) {
        return data.get(row)[column];
    }

    // Ghi đè và viết code
    // cho phương thức chèn giá trị mới vào ô.       
    @Override
    public void setValueAt(Object value, int row, int column) {
        //data.get(row)[column] = value;
        fireTableCellUpdated(row, column);
    }
   
}

Bạn hãy tiến hành build trước lớp này trước khi bắt các bước tiếp theo. Giờ bạn quay trở lại lớp main  để khai báo và khởi tạo lớp "myAbstractTableModel" vừa tạo xong.

private myAbstractTableModel matm;

Để tránh rối tôi sẽ tạo riêng một phướng thức cho việc tạo JTable như sau:

private void createTable() {

    String[] header;
    header = new String[]{"Name", "Quantity"};

    ArrayList<Object[]> data = new ArrayList<>();

    data.add(new Object[]{"Apple", "123"});
    data.add(new Object[]{"Banana", "456"});
    data.add(new Object[]{"Cranberry", "789"});       

    matm = new myAbstractTableModel(header, data);

    jTable1.setModel(matm);

}


Việc còn lại tương đối đương giản là bạn chỉ việc gọi phương thức "createTable" phương thức khởi tạo "jtable_with_model" là được.


Sau khi hoàn tất các bước bạn chỉ việc build run chương trình để thấy kết quả như sau:


Tất nhiên đây chỉ là một phần của JTable, chính xác mà nói bài này chỉ hướng dẫn cách load dữ liệu lên JTable thông qua model AbstractTableModel, còn việc thêm(add), xóa(delete), sửa(update).... để tránh bài học quá dài và tránh tăng độ phức tạp nên tôi sẽ biên soạn một bài viết khác về các vấn đề này sau, mong được sự theo dõi của các bạn.

Sẵn nói qua chút, nếu bạn để ý trong code ở trên có đoạn sau:

    // Ghi đè và viết code
    // cho phương thức chèn giá trị mới vào ô.       
    @Override
    public void setValueAt(Object value, int row, int column) {
        //data.get(row)[column] = value;
        fireTableCellUpdated(row, column);
    }

Điều này có nghĩa là các phương thức như thêm dòng, xóa dòng, chỉnh sửa dữ liệu của bảng, bạn phải đều tự mình thiết lập các phương thức khi sử dụng lớp AbstractTableModel này.

Ngoài ra tùy vào ý đồ của lập trình viên thì các phương thức này sẽ được áp dụng thì các phương thức này sẽ được sử dụng các sự kiện khác nhau như button event, menu evet, mouse event.... và việc áp dụng mấy cái này cũng tương đối khó theo từng trược hợp cụ thể ^^!


Write: +Bui Ngoc Son




4 comments:

  1. bài viết rất hay tks bạn!

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. mình viết đến đây thì lỗi bạn ạ - chỗ colum
    return listCars.get(row)[colum];
    với listCars : ArrayList listCars // cars lớp miêu tả về các xe oto.

    ReplyDelete