Ustawienie szerokości kolumny w języku Java JTable

95

Mam JTable, w którym ustawiam rozmiar kolumny w następujący sposób:

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);

Działa to dobrze, ale gdy tabela jest zmaksymalizowana, po prawej stronie ostatniej kolumny pojawia się puste miejsce. Czy podczas zmiany rozmiaru można zmienić rozmiar ostatniej kolumny na koniec okna?

znalazłem AUTO_RESIZE_LAST_COLUMN właściwość w dokumentach, ale to nie działa.

Edycja: JTablejest ustawiony w JScrollPanepreferowanym rozmiarze.

Hamza Yerlikaya
źródło

Odpowiedzi:

45

Co się stanie, jeśli zadzwonisz setMinWidth(400)na ostatniej kolumnie zamiast z setPreferredWidth(400)?

W JavaDoc for JTable, przeczytaj doLayout()uważnie dokumentację . Oto kilka bitów do wyboru:

Gdy metoda jest wywoływana w wyniku zmiany rozmiaru otaczającego okna, resizingColumn ma wartość null. Oznacza to, że zmiana rozmiaru odbyła się „poza” tabelą JTable i zmiana - lub „delta” - powinna zostać rozesłana do wszystkich kolumn niezależnie od trybu automatycznej zmiany rozmiaru tego JTable.

Może dlatego AUTO_RESIZE_LAST_COLUMNci nie pomogło.

Uwaga: Kiedy JTable dostosowuje szerokości kolumn, bezwzględnie przestrzega ich wartości minimalnych i maksymalnych.

Oznacza to, że możesz chcieć ustawić Min == Max dla wszystkich kolumn oprócz ostatniej, a następnie ustawić Min = Preferred w ostatniej kolumnie i albo nie ustawiać Max, albo ustawić bardzo dużą wartość Max.

Eddie
źródło
1
setMinWidth (400) nadal powoduje, że prawa część tabeli jest pusta
Hamza Yerlikaya.
2
Spróbuj dodać setMaxWidth (10000), aby zobaczyć, czy to robi różnicę.
Eddie
1
Usuń wiersz table.setAutoResizeMode (JTable.AUTO_RESIZE_OFF); Może to uniemożliwić zmianę rozmiaru.
Eddie
Prawdopodobnie chcesz również ustawić minimalny i maksymalny rozmiar w samym JTable, jeśli jeszcze tego nie zrobiłeś,
Eddie,
3
Upewnij się, że wykonujesz wywołanie setMinWidth po zastosowaniu modelu tabeli ... To mnie raz na chwilę zaskoczyło .
Brian Knoblauch
23

W JTable.AUTO_RESIZE_OFFprzypadku tabeli nie zmieni ona rozmiaru żadnej z kolumn, więc przyjmie preferowane ustawienie. Jeśli Twoim celem jest ustawienie domyślnych kolumn na preferowany rozmiar, z wyjątkiem tego, aby ostatnia kolumna wypełniała resztę okienka, możesz użyć opcji JTable.AUTO_RESIZE_LAST_COLUMNautoResizeMode, ale może być najbardziej efektywna, gdy zostanie użyta z TableColumn.setMaxWidth()zamiast TableColumn. setPreferredWidth () dla wszystkich kolumn oprócz ostatniej.

Gdy upewnisz się, że AUTO_RESIZE_LAST_COLUMNto faktycznie działa, możesz poeksperymentować z kombinacją TableColumn.setMaxWidth()iTableColumn.setMinWidth()

akf
źródło
1
Kiedy używana jest funkcja AUTO_RESIZE_LAST_COLUMN, rozmiar tabeli jest zmieniany tak, aby pasował do okienka przewijania, moim celem jest, aby tabela miała określony minimalny rozmiar, ale aby rosła, jeśli jest większa niż mój minimalny rozmiar.
Hamza Yerlikaya
Możesz mieć takie zachowanie, jeśli używasz TableColumn.setMinWidth () zamiast TableColumn.setMaxWidth ().
akf
dodać do mojego ostatniego komentarza: użyj TableColumn.setMinWidth () dla każdej kolumny w twojej tabeli, łącznie z ostatnią kolumną.
akf
ustawienie minimalnej i maksymalnej szerokości rozwiązało problem, ale teraz brakuje pasków przewijania.
Hamza Yerlikaya
16

JTable.AUTO_RESIZE_LAST_COLUMNjest zdefiniowana jako „Podczas wszystkich operacji zmiany rozmiaru zastosuj korekty tylko do ostatniej kolumny”, co oznacza, że ​​musisz ustawić tryb autoresizemode na końcu kodu , w przeciwnym razie metoda setPreferredWidth () nie będzie miała żadnego wpływu!

Więc w twoim przypadku byłby to właściwy sposób:

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);
Rico Ocepek
źródło
5

Użyj tej metody

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;
    }
}

Lub rozszerz JTableklasę:

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;
        }
    }
}

I wtedy

table.setColumnWidths(30, 150, 100, 100);
Oleg Michajłow
źródło
4

Czytając uwagę Kleopatry (po raz drugi zasugerowała, aby rzucić okiem na javax.swing.JXTable , a teraz przepraszam, że nie spojrzałem za pierwszym razem :)) Proponuję podążać za linkiem

Miałem to rozwiązanie dla tego samego problemu: (ale sugeruję skorzystanie z powyższego łącza) Przy zmianie rozmiaru tabeli przeskaluj szerokości kolumn tabeli do bieżącej całkowitej szerokości tabeli. aby to zrobić, używam globalnej tablicy int dla (względnych) szerokości kolumn):

private int[] columnWidths=null;

Używam tej funkcji do ustawienia szerokości kolumn tabeli:

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);
    }

}

Podczas ustawiania danych dzwonię:

    setColumnWidths(this.columnWidths);

a po zmianie wywołuję ComponentListener ustawiony na rodzica tabeli (w moim przypadku JScrollPane, który jest kontenerem mojej tabeli):

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

zwróć uwagę, że tabela JTable jest również globalna:

private JTable table;

I tutaj ustawiam słuchacza:

    scrollPane=new JScrollPane(table);
    scrollPane.addComponentListener(this);
michel.iamit
źródło
1
o ile widzę, jest to (bardzo kruchy) hack: nie aktualizuje się, gdy użytkownik zmienia szerokość kolumny. Ponownie sugerowałbym zajrzeć do kodu źródłowego JXTable - ma dodatkową właściwość horizontalScroll, która uruchamia wypełnianie dostępnej szerokości, jeśli suma preferencji kolumn jest mniejsza niż bieżąca szerokość, aw przeciwnym razie pokazuje poziomy pasek przewijania
kleopatra
Wiem, że nie reaguje na ręczną zmianę szerokości stołu przez użytkownika, w ten sposób to hack ... ale znowu: lepiej niż sugerowano powyżej. Ale zaciekawiła mnie JXTable ... Zajrzę tam! (i miło znów do Ciebie
podejść
Miałeś rację, zobacz moją uwagę obok mojej odpowiedzi, zagłosowałem za twoją uwagą!
michel.iamit
Przynajmniej było to dla mnie przydatne, zastosowałem to podejście w moim przypadku z zasadą ciężaru kolumny.
Solostaran14
2
fireTableStructureChanged();

domyślnie zmieni rozmiar ! Jeśli ta metoda zostanie wywołana gdzieś w kodzie PO ustawieniu właściwości zmiany rozmiaru kolumny, wszystkie ustawienia zostaną zresetowane. Ten efekt uboczny może wystąpić pośrednio. Fe w wyniku zmiany połączonego modelu danych w sposób wywoływany przez tę metodę po ustawieniu właściwości.

count0
źródło
1

Nie ma potrzeby korzystania z tej opcji, po prostu ustaw preferowaną szerokość ostatniej kolumny na maksimum, a zajmie to całą dodatkową przestrzeń.

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);
David Newcomb
źródło
0

Ten kod działa dla mnie bez 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);
Harsha Sampath
źródło
-2

Użyj tego kodu. U mnie to zadziałało. Rozważałem za 3 kolumny. Zmień wartość pętli dla swojego kodu.

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);
}
Arijit
źródło