Cài đặt Java JTable Chiều rộng cột


95

Tôi có một JTable, trong đó tôi đặt kích thước cột như sau:

table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getColumnModel().getColumn(0).setPreferredWidth(27);
table.getColumnModel().getColumn(1).setPreferredWidth(120);
table.getColumnModel().getColumn(2).setPreferredWidth(100);
table.getColumnModel().getColumn(3).setPreferredWidth(90);
table.getColumnModel().getColumn(4).setPreferredWidth(90);
table.getColumnModel().getColumn(6).setPreferredWidth(120);
table.getColumnModel().getColumn(7).setPreferredWidth(100);
table.getColumnModel().getColumn(8).setPreferredWidth(95);
table.getColumnModel().getColumn(9).setPreferredWidth(40);
table.getColumnModel().getColumn(10).setPreferredWidth(400);

Điều này hoạt động tốt, nhưng khi bảng được tối đa hóa, tôi nhận được không gian trống ở bên phải của cột cuối cùng. Có thể thực hiện thay đổi kích thước cột cuối cùng thành cuối cửa sổ khi thay đổi kích thước không?

Tôi đã tìm thấy AUTO_RESIZE_LAST_COLUMNtài sản trong tài liệu nhưng nó không hoạt động.

Chỉnh sửa: JTablelà một JScrollPanekích thước ưa thích của nó được thiết lập.

Câu trả lời:


45

Chuyện gì xảy ra nếu bạn gọi setMinWidth(400)vào cột cuối cùng thay vì của setPreferredWidth(400)?

Trong JavaDoc cho JTable, hãy đọc tài liệu cho doLayout()thật cẩn thận. Dưới đây là một số bit lựa chọn:

Khi phương thức được gọi là kết quả của việc thay đổi kích thước của một cửa sổ bao quanh, thì resizingColumn là null. Điều này có nghĩa là thay đổi kích thước đã diễn ra "bên ngoài" JTable và thay đổi - hoặc "delta" - sẽ được phân phối cho tất cả các cột bất kể chế độ thay đổi kích thước tự động của JTable này.

Đây có thể là lý do tại sao AUTO_RESIZE_LAST_COLUMNkhông giúp bạn.

Lưu ý: Khi một JTable thực hiện điều chỉnh độ rộng của các cột, nó sẽ tôn trọng tuyệt đối các giá trị tối thiểu và tối đa của chúng.

Điều này nói rằng bạn có thể muốn đặt Min == Max cho tất cả trừ các cột cuối cùng, sau đó đặt Min = Preferred trên cột cuối cùng và không đặt Max hoặc đặt giá trị rất lớn cho Max.


1
setMinWidth (400) vẫn còn làm cho bên phải của bảng để có sản phẩm nào
Hamza Yerlikaya

2
Hãy thử thêm setMaxWidth (10000) để xem điều đó có tạo ra sự khác biệt hay không.
Eddie

1
Loại bỏ bảng dòng.setAutoResizeMode (JTable.AUTO_RESIZE_OFF); Điều này có thể ngăn thay đổi kích thước mà bạn muốn.
Eddie

Bạn có thể cũng muốn đặt kích thước tối thiểu và tối đa trên chính JTable, nếu bạn chưa đặt,
Eddie

3
Đảm bảo rằng bạn thực hiện lệnh gọi setMinWidth sau khi áp dụng mô hình bảng ... Điều đó đã khiến tôi vấp phải một lần trong một thời gian.
Brian Knoblauch

23

Với JTable.AUTO_RESIZE_OFF, bảng sẽ không thay đổi kích thước của bất kỳ cột nào đối với bạn, vì vậy nó sẽ sử dụng cài đặt ưa thích của bạn. Nếu mục tiêu của bạn là đặt các cột mặc định theo kích thước ưa thích của bạn, ngoại trừ việc để cột cuối cùng lấp đầy phần còn lại của ngăn, Bạn có tùy chọn sử dụng JTable.AUTO_RESIZE_LAST_COLUMNAutoResizeMode, nhưng nó có thể hiệu quả nhất khi được sử dụng TableColumn.setMaxWidth()thay vì TableColumn. setPreferredWidth () cho tất cả trừ cột cuối cùng.

Khi bạn hài lòng rằng điều AUTO_RESIZE_LAST_COLUMNđó trên thực tế hoạt động, bạn có thể thử nghiệm với sự kết hợp của TableColumn.setMaxWidth()TableColumn.setMinWidth()


1
Khi AUTO_RESIZE_LAST_COLUMN được sử dụng, bảng được thay đổi kích thước để vừa với ngăn cuộn, mục tiêu của tôi là có bảng ở kích thước tối thiểu nhất định nhưng làm cho nó phát triển nếu nó lớn hơn kích thước tối thiểu của tôi.
Hamza Yerlikaya

Bạn có thể có hành vi này nếu bạn sử dụng TableColumn.setMinWidth () thay vì TableColumn.setMaxWidth ().
akf

để thêm vào nhận xét cuối cùng của tôi: sử dụng TableColumn.setMinWidth () cho mỗi cột trong bảng của bạn, bao gồm cả cột cuối cùng.
akf

đặt cả chiều rộng tối thiểu và chiều rộng tối đa đã giải quyết được vấn đề nhưng bây giờ các thanh cuộn bị lỗi.
Hamza Yerlikaya

14

JTable.AUTO_RESIZE_LAST_COLUMNđược định nghĩa là "Trong tất cả các hoạt động thay đổi kích thước, chỉ áp dụng điều chỉnh cho cột cuối cùng" có nghĩa là bạn phải đặt mã tự động ở cuối mã của mình , nếu không setPreferredWidth () sẽ không ảnh hưởng gì!

Vì vậy, trong trường hợp của bạn, đây sẽ là cách chính xác:

table.getColumnModel().getColumn(0).setPreferredWidth(27);
table.getColumnModel().getColumn(1).setPreferredWidth(120);
table.getColumnModel().getColumn(2).setPreferredWidth(100);
table.getColumnModel().getColumn(3).setPreferredWidth(90);
table.getColumnModel().getColumn(4).setPreferredWidth(90);
table.getColumnModel().getColumn(6).setPreferredWidth(120);
table.getColumnModel().getColumn(7).setPreferredWidth(100);
table.getColumnModel().getColumn(8).setPreferredWidth(95);
table.getColumnModel().getColumn(9).setPreferredWidth(40);
table.getColumnModel().getColumn(10).setPreferredWidth(400);
table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);

5

Sử dụng phương pháp này

public static void setColumnWidths(JTable table, int... widths) {
    TableColumnModel columnModel = table.getColumnModel();
    for (int i = 0; i < widths.length; i++) {
        if (i < columnModel.getColumnCount()) {
            columnModel.getColumn(i).setMaxWidth(widths[i]);
        }
        else break;
    }
}

Hoặc mở rộng JTablelớp học:

public class Table extends JTable {
    public void setColumnWidths(int... widths) {
        for (int i = 0; i < widths.length; i++) {
            if (i < columnModel.getColumnCount()) {
                columnModel.getColumn(i).setMaxWidth(widths[i]);
            }
            else break;
        }
    }
}

Và sau đó

table.setColumnWidths(30, 150, 100, 100);

4

Đọc nhận xét của Kleopatra (lần thứ hai cô ấy đề nghị xem javax.swing.JXTable , và bây giờ tôi xin lỗi vì tôi đã không xem lần đầu tiên :)) Tôi đề nghị bạn theo liên kết

Tôi đã có giải pháp này cho cùng một vấn đề: (nhưng tôi khuyên bạn nên làm theo liên kết ở trên) Khi thay đổi kích thước bảng, hãy chia tỷ lệ chiều rộng cột bảng thành tổng chiều rộng bảng hiện tại. để làm điều này, tôi sử dụng một mảng toàn cục gồm các int cho độ rộng cột (tương đối)):

private int[] columnWidths=null;

Tôi sử dụng hàm này để đặt độ rộng cột của bảng:

public void setColumnWidths(int[] widths){
    int nrCols=table.getModel().getColumnCount();
    if(nrCols==0||widths==null){
        return;
    }
    this.columnWidths=widths.clone();

    //current width of the table:
    int totalWidth=table.getWidth();

    int totalWidthRequested=0;
    int nrRequestedWidths=columnWidths.length;
    int defaultWidth=(int)Math.floor((double)totalWidth/(double)nrCols);

    for(int col=0;col<nrCols;col++){
        int width = 0;
        if(columnWidths.length>col){
            width=columnWidths[col];
        }
        totalWidthRequested+=width;
    }
    //Note: for the not defined columns: use the defaultWidth
    if(nrRequestedWidths<nrCols){
        log.fine("Setting column widths: nr of columns do not match column widths requested");
        totalWidthRequested+=((nrCols-nrRequestedWidths)*defaultWidth);
    }
    //calculate the scale for the column width
    double factor=(double)totalWidth/(double)totalWidthRequested;

    for(int col=0;col<nrCols;col++){
        int width = defaultWidth;
        if(columnWidths.length>col){
            //scale the requested width to the current table width
            width=(int)Math.floor(factor*(double)columnWidths[col]);
        }
        table.getColumnModel().getColumn(col).setPreferredWidth(width);
        table.getColumnModel().getColumn(col).setWidth(width);
    }

}

Khi thiết lập dữ liệu, tôi gọi:

    setColumnWidths(this.columnWidths);

và khi thay đổi, tôi gọi bộ ComponentListener là cha của bảng (trong trường hợp của tôi, JScrollPane là vùng chứa của bảng của tôi):

public void componentResized(ComponentEvent componentEvent) {
    this.setColumnWidths(this.columnWidths);
}

lưu ý rằng bảng JTable cũng là toàn cầu:

private JTable table;

Và ở đây tôi thiết lập trình nghe:

    scrollPane=new JScrollPane(table);
    scrollPane.addComponentListener(this);

1
Theo như tôi thấy, đây là một vụ hack (rất giòn): nó không cập nhật khi người dùng thay đổi chiều rộng cột. Một lần nữa, tôi sẽ đề nghị bạn nhìn vào mã nguồn của JXTable - nó có một horizontalScroll additional property mà trigger điền chiều rộng có sẵn nếu tổng của prefs cột nhỏ hơn chiều rộng và các chương trình hiện một thanh cuộn ngang khác
Kleopatra

Tôi biết nó không phản ứng với việc người dùng thay đổi độ rộng của bảng theo cách thủ công, theo cách đó, đó là một cuộc tấn công ... nhưng một lần nữa: nó tốt hơn đề xuất ở trên. Nhưng bạn đã khiến tôi tò mò với JXTable .... Tôi sẽ xem ở đó! (và tốt đẹp để đi bộ ở với anh nữa về một chủ đề bàn :))
michel.iamit

Bạn đã đúng, hãy xem nhận xét của tôi trên đầu câu trả lời của tôi, tôi đã ủng hộ nhận xét của bạn!
michel.iamit

Ít nhất điều này cũng hữu ích cho tôi, tôi đã sử dụng cách tiếp cận này cho trường hợp của mình với nguyên tắc trọng số cột.
Solostaran 14

2
fireTableStructureChanged();

sẽ mặc định hành vi thay đổi kích thước ! Nếu phương thức này được gọi ở đâu đó trong mã của bạn SAU KHI bạn đã đặt thuộc tính thay đổi kích thước cột, tất cả các cài đặt của bạn sẽ được đặt lại. Tác dụng phụ này có thể xảy ra gián tiếp. Fe do mô hình dữ liệu liên kết bị thay đổi theo cách mà phương pháp này được gọi, sau khi các thuộc tính được thiết lập.


1

Không cần tùy chọn, chỉ cần đặt chiều rộng ưu tiên của cột cuối cùng là tối đa và nó sẽ chiếm tất cả không gian thừa.

table.getColumnModel().getColumn(0).setPreferredWidth(27);
table.getColumnModel().getColumn(1).setPreferredWidth(120);
table.getColumnModel().getColumn(2).setPreferredWidth(100);
table.getColumnModel().getColumn(3).setPreferredWidth(90);
table.getColumnModel().getColumn(4).setPreferredWidth(90);
table.getColumnModel().getColumn(6).setPreferredWidth(120);
table.getColumnModel().getColumn(7).setPreferredWidth(100);
table.getColumnModel().getColumn(8).setPreferredWidth(95);
table.getColumnModel().getColumn(9).setPreferredWidth(40);
table.getColumnModel().getColumn(10).setPreferredWidth(Integer.MAX_INT);

0

Mã này được làm việc cho tôi mà không có setAutoResizeModes.

        TableColumnModel columnModel = jTable1.getColumnModel();
        columnModel.getColumn(1).setPreferredWidth(170);
        columnModel.getColumn(1).setMaxWidth(170);
        columnModel.getColumn(2).setPreferredWidth(150);
        columnModel.getColumn(2).setMaxWidth(150);
        columnModel.getColumn(3).setPreferredWidth(40);
        columnModel.getColumn(3).setMaxWidth(40);

-1

Sử dụng mã này. Nó đã làm việc cho tôi. Tôi đã xem xét cho 3 cột. Thay đổi giá trị vòng lặp cho mã của bạn.

TableColumn column = null;
for (int i = 0; i < 3; i++) {
    column = table.getColumnModel().getColumn(i);
    if (i == 0) 
        column.setMaxWidth(10);
    if (i == 2)
        column.setMaxWidth(50);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.