Sử dụng JTable của Swing trong java (phần 2)

https://codersontrang.com/2012/08/22/su-dung-jtable-cua-swing-trong-java-phan-2/

Trong phần 1 chúng ta đã biết cách đưa dữ liệu từ một TableModel lên một JTable. Trong phần này chúng ta sẽ tiếp tục tìm hiểu về cách sử dụng JTable của Swing trong java như là tạo cửa sổ cuộn cho bảng, tạo tiêu đề cho các cột trong bảng và thao tác với hàng và cột.

Tạo cửa sổ cuộn cho bảng

Trong bất cứ trường hợp nào mà ở đó chúng ta có một số lượng lớn thông tin cần hiển thị, chúng ta sẽ cần đến lớp JScrollPane. Lớp này tạo ra một cửa sổ cuộn cho phép chúng ta nhìn một lượng lớn thông tin chỉ bằng thao tác kéo thanh cuộn trên cửa sổ. Trở lại ví dụ lần trước chúng ta chỉ cần thay đổi vài dòng trong lớp SimpleTableTest trong file SimpleTableTest.java. Trong đoạn code dưới đây, những dòng in đậm màu xanh là những dòng thêm mới vào đoạn code cũ.


public class SimpleTableTest extends JFrame{
    protected JTable table;

    public SimpleTableTest(){
        [...]
        table = new JTable(tv);
        

JScrollPane jsp = new JScrollPane(table); pane.add(jsp, BorderLayout.CENTER);

} public static void main(String [] args){ [...] } }

Bây giờ chạy chương trình chúng ta sẽ thấy một thanh cuộn xuất hiện khi mà kích thước cửa sổ nhỏ hơn kích thước của bảng như hình dưới đây

Nếu để ý chúng ta cũng thấy việc tạo một cửa sổ cuộn cho bảng cũng sẽ làm xuất hiện tiêu đề cho các cột. Theo mặc định, tiêu đề các cột sẽ lần lượt được đánh theo thứ tự bảng chữ cái bắt đầu từ A rồi đến B, C… Vậy để làm sao cho tiêu đề của các cột đúng với những tên mà chúng ta mong muốn. Phần dưới đây sẽ hướng dẫn tạo tiêu đề cho các cột.

Tạo tiêu đề cho các cột trong bảng

Trước tiên phải nhớ tạo ra một cửa sổ cuộn cho bảng đã. Nếu như không tạo cửa sổ cuộn cho bảng thì tiêu đề các cột cũng không thể xuất hiện. Sau đó, chúng ta có thể đặt tên cho tiêu đề của các cột trong bảng bằng cách cài đặt phương thức getColumnName() trong TableModel của chúng ta. Trong ví dụ, chúng ta chỉ việc sửa lớp TableValues bằng cách thêm vào các đoạn mã màu xanh sau:


public class TableValues 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 = { [...] }; public int getRowCount() { return values.length; } public int getColumnCount() { return values[0].length; } public Object getValueAt(int rowIndex, int columnIndex) { return values[rowIndex][columnIndex]; }

@Override public String getColumnName(int column){ return columnNames[column]; }

}

Giờ chạy chương trình, các tiêu đề ở các cột đã có tên rất đàng hoàng

Chúng ta để ý rằng khi mà kích thước cửa sổ nhỏ hơn kích thước của bảng. Một thanh cuộn dọc sẽ xuất hiện nhưng lại không có một thanh cuộn ngang. Thay vào đó, các cột trong bảng sẽ tự động co lại giống như hình dưới đây.

Để hiểu tại sao điều này lại xảy ra, chúng ta cần phải tìm hiểu về thiết kế của JTable và các lớp hỗ trợ của nó làm việc như thế nào.

Thiết kế hướng cột (column-oriented design) của JTable

Thành phần JTable được thiết kế hướng cột, mỗi một JTable sẽ có một tham chiếu đến một cài đặt của interface TableColumnModel. Một cài đặt của TableColumnModel chẳng hạn như DefaultTableColumnModel nằm trong gói javax.swing.table và miêu tả một tập hợp các cột ở trong một cái JTable. Mỗi một cột được biểu diễn là một đối tượng của lớp TableColumn. Cho ví dụ như sau, giả sử chúng ta tạo một TableModel trong đó số cột của bảng được chỉ định là 5. Nếu sau đó chúng ta tạo một đối tượng của lớp JTable và đối tượng này sử dụng cái model vừa tạo thì lúc đó một đối tượng của lớp DefaultTableColumnModel sẽ được tạo ra. Đối tượng của lớp JTable sẽ lấy thông tin về số cột của bảng từ TableModel, sau đó tạo ra 5 đối tượng của lớp TableColumn rồi thêm 5 đối tượng này vào đối tượng của lớp DefaultTableColumnModel vừa tạo trước đó.

Mỗi đối tượng của lớp TableColumn mang thông tin cho một cột như tiêu đề của cột đó, giá trị về độ rộng hiện tại, độ rộng nhỏ nhất, độ rộng lớn nhất, độ rộng được ưa thích của cột đó, chỉ định xem cột đó có được phép thay đổi kích thước hay không. Ban đầu, khi mà được tạo, độ rộng hiện tại và độ rộng ưa thích của một cột được đặt giá trị là 75, độ rộng nhỏ nhất là 15 và độ rộng lớn nhất được đặt đến vô hạn (Integer.MAX_VALUE).

Sau khi chúng ta tạo một cột, chúng ta có thể thay đổi giá trị độ rộng của cột một cách trực tiếp bằng việc sử dụng các phương thức như setWith, setMaxWith, setMinWidth, setPreferedWidth.

Mỗi một đối tượng của lớp JTable đều được thiết lập một chế độ để chỉ ra cách nó xử lý khi mà kích thước của nó bị thay đổi. Chế độ này có thể rơi vào một trong 5 giá trị. Mỗi giá trị tương ứng với một hằng số được định nghĩa trong JTable như sau:

  • AUTO_RESIZE_ALL_COLUMNS
  • AUTO_RESIZE_LAST_COLUMN
  • AUTO_RESIZE_NEXT_COLUMN
  • AUTO_RESIZE_OFF
  • AUTO_RESIZE_SUBSEQUENT_COLUMNS

Những giá trị này quy định cách các cột của bảng thay đổi kích thước khi mà độ rộng của bảng hoặc một trong bảng thay đổi giá trị.

Sự thay đổi kích thước của bảng

Nếu chế độ tự động thay đổi kích thước của bảng được đặt giá trị là AUTO_RESIZE_OFF thì việc thay đổi kích thước của bảng không làm ảnh hưởng đến kích thước hiện tại của các cột trong bảng đó. Nhưng nếu nó nhận một trong bốn giá trị còn lại thì một sự thay đổi về kích thước của bảng sẽ được phân phối đều đến tất cả các cột trong bảng theo tỷ lệ dựa trên kích thước ưa thích (prefered width) của các cột. Cho ví dụ, giả sử rằng một bảng có hai cột trong đó một cột có độ rộng ưa thích là 200 và cột còn lại có độ rộng ưa thích là 100. Trong trường hợp này, cột thứ nhất sẽ chiếm hai phần ba chiều rộng của bảng, và cột thứ hai chiếm một phần ba độ rộng còn lại. Nếu bảng đó được kéo rộng ra thêm 30 pixel thì cột thứ nhất sẽ rộng ra thêm 20 pixels và cột thứ hai rộng ra thêm 10 pixel.

Nếu chế độ tự động thay đổi kích thước của bảng được đặt giá trị là AUTO_RESIZE_OFF, và tổng độ rộng của tất cả các cột lớn hơn độ rộng của bảng thì khi đó thanh cuộn ngang sẽ xuất hiện. Bây giờ quay trở lại ví dụ, ta thay đổi contructor của lớp SimpleTableTest như sau:


public class SimpleTableTest extends JFrame{
    protected JTable table;

    public SimpleTableTest(){
        [...]
        table = new JTable(tv);
        

table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

JScrollPane jsp = new JScrollPane(table); pane.add(jsp, BorderLayout.CENTER); } public static void main(String [] args){ [...] } }

Mỗi cột có một độ rộng mặc định là 75, khi độ rộng của bảng quá nhỏ để hiển thị tất cả các cột, một thanh trượt ngang xuất hiện như hình dưới đây:

Sự thay đổi kích thước của cột

Chúng ta đã được thấy việc thay đổi độ rộng của một bảng ảnh hưởng như thế nào đến độ rộng của các cột bên trong bảng đó. Chúng ta còn phải xem xét đến việc thay đổi kích thước của một cột sẽ ảnh hưởng đến kích thước của các cột khác như thế nào. Chúng ta có thể thay đổi kích thước của cột bằng việc gọi các phương thức trong code hoặc có thể thay đổi qua giao diện của JTable.

Khi kích thước của một cột thay đổi, nó sẽ ảnh hưởng đến kích thước của các cột khác tùy thuộc vào việc chế độ tự động thay đổi kích thước của bảng được đặt giá trị như thế nào. Trong phần này, chúng ta sẽ xem xét sự thay đổi trên mỗi giá trị cụ thể.

AUTO_RESIZE_OFF
Ở chế độ này khi một cột thay đổi kích thước sẽ không làm ảnh hưởng đến kích thước của các cột khác trong bảng. Nếu kích thước của bảng nhỏ hơn tổng kích thước của tất cả các cột, thanh trượt nằm ngang sẽ xuất hiện. Nếu kích thước của bảng lớn hơn tổng kích thước của tất cả các cột, sẽ có những khoảng trống trong bảng như hình dưới đây

AUTO_RESIZE_NEXT_COLUMN

Trong chế độ này, khi một cột thay đổi kích thước thì cột bên phải liền sát nó sẽ được nới rộng hoặc bị co lại. Trong hình dưới đây, cột Date of Birth tăng kích thước, cột phía bên phải liền sát nó là cột Account Balance sẽ bị co lại

AUTO_RESIZE_SUBSEQUENT_COLUMNS

Trường hợp này gần giống như trường hợp sử dụng AUTO_RESIZE_NEXT_COLUMN, ngoại trừ rằng khi một cột thay đổi kích thước thì tất cả các cột phía bên phải nó sẽ được mở rộng hay co lại. Trong hình dưới đây, cột Date of Birth mở rộng ra khiến hai cột phía bên phải nó là Account Balance và Gender bị co lại

Độ chênh lệch giữa kích thước ban đầu và kích thước về sau của cột có kích thước bị thay đổi (trong ví dụ là cột Date of Birth) gọi là giá trị delta. Giá trị này được phân phối theo tỷ lệ đến các cột phía bên phải cột đó.

AUTO_RESIZE_LAST_COLUMN

Trong chế độ này, giá trị delta được phân phối đến cột cuối cùng của bảng và có thể làm cho độ rộng của nó lớn hơn hoặc nhỏ đi. Trong hình dưới đây, khi kích thước của cột Date of Birth tăng lên là nguyên nhân cột Gender bị co lại

AUTO_RESIZE_ALL_COLUMNS

Đây chính là chế độ mặc định cho một JTable nếu chúng ta không chỉ định chế độ tự động thay đổi kích thước cho nó. Trong chế độ này, nếu ta thay đổi kích thước cho một cột, tất cả các cột khác trong bảng cũng sẽ thay đổi kích thước theo tỷ lệ. Trong hình dưới đây, cột Date of Birth tăng kích thước làm cho tất cả các cột khác nhỏ đi.

Đến đây, có một vấn đề là định dạng dữ liệu trong các cột chưa được theo ý muốn. Ví dụ, giá trị dữ liệu ở cột giới tính hiển thị là “true” và “false” trong khi nhẽ ra phải là “Male” và “Female” mới chuẩn. Hoặc như cột tài khoản hiển thị các giá trị kiểu số nhưng lại không theo chuẩn định dạng của tiền tệ.

Tất cả những vẫn đề này sẽ được giải quyết trong phần 3.

Nguồn: Brett Spell – Pro Java Programming, Second Edition

Chia sẻ bài viết

Thích bài này:

Thích

Đang tải…