Java JTable-Einstellung Spaltenbreite

95

Ich habe eine JTable, in der ich die Spaltengröße wie folgt einstelle:

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

Dies funktioniert gut, aber wenn die Tabelle maximiert ist, wird rechts von der letzten Spalte ein leerer Bereich angezeigt. Ist es möglich, die Größe der letzten Spalte bis zum Ende des Fensters zu ändern, wenn die Größe geändert wird?

Ich habe eine AUTO_RESIZE_LAST_COLUMNEigenschaft in Dokumenten gefunden, aber es funktioniert nicht.

Bearbeiten: JTableist in einer JScrollPaneseiner bevorzugten Größen eingestellt.

Hamza Yerlikaya
quelle

Antworten:

45

Was passiert , wenn Sie rufen setMinWidth(400)auf der letzten Spalte statt von setPreferredWidth(400)?

JTableLesen Sie im JavaDoc für die Dokumente doLayout()sehr sorgfältig durch. Hier sind einige Auswahlbits:

Wenn die Methode als Ergebnis der Größenänderung eines umschließenden Fensters aufgerufen wird, ist die resizingColumn null. Dies bedeutet, dass die Größenänderung "außerhalb" der JTable stattgefunden hat und die Änderung - oder "Delta" - unabhängig vom automatischen Größenänderungsmodus dieser JTable auf alle Spalten verteilt werden sollte.

Dies könnte der Grund sein, warum AUTO_RESIZE_LAST_COLUMNes Ihnen nicht geholfen hat.

Hinweis: Wenn eine JTable die Breite der Spalten anpasst, werden deren Minimal- und Maximalwerte absolut berücksichtigt.

Dies bedeutet, dass Sie möglicherweise Min == Max für alle außer den letzten Spalten festlegen möchten, dann Min = Preferred für die letzte Spalte festlegen und entweder Max nicht festlegen oder einen sehr großen Wert für Max festlegen möchten.

Eddie
quelle
1
setMinWidth (400) bewirkt immer noch, dass das Recht der Tabelle leer ist
Hamza Yerlikaya
2
Versuchen Sie, setMaxWidth (10000) hinzuzufügen, um festzustellen, ob dies einen Unterschied macht.
Eddie
1
Entfernen Sie die Zeile table.setAutoResizeMode (JTable.AUTO_RESIZE_OFF). Dies kann die gewünschte Größenänderung verhindern.
Eddie
Sie möchten wahrscheinlich auch die minimale und maximale Größe auf der JTable selbst festlegen, falls Sie dies noch nicht getan haben
Eddie
3
Stellen Sie sicher, dass Sie den Aufruf setMinWidth ausführen, nachdem Sie das Tabellenmodell angewendet haben ... Das hat mich einmal für eine Weile gestolpert.
Brian Knoblauch
23

Mit JTable.AUTO_RESIZE_OFFändert die Tabelle die Größe einer der Spalten für Sie nicht, sodass Ihre bevorzugte Einstellung verwendet wird. Wenn es Ihr Ziel ist, die Spalten standardmäßig auf Ihre bevorzugte Größe zu bringen, außer dass die letzte Spalte den Rest des JTable.AUTO_RESIZE_LAST_COLUMNBereichs ausfüllt, haben Sie die Möglichkeit, den autoResizeMode zu verwenden. Dies ist jedoch möglicherweise am effektivsten, wenn Sie TableColumn.setMaxWidth()anstelle von TableColumn verwendet werden. setPreferredWidth () für alle außer der letzten Spalte.

Sobald Sie zufrieden sind, dass AUTO_RESIZE_LAST_COLUMNdies tatsächlich funktioniert, können Sie mit einer Kombination aus TableColumn.setMaxWidth()und experimentierenTableColumn.setMinWidth()

akf
quelle
1
Wenn AUTO_RESIZE_LAST_COLUMN verwendet wird, wird die Größe der Tabelle so angepasst, dass sie in den Bildlaufbereich passt. Mein Ziel ist es, die Tabelle auf eine bestimmte Mindestgröße zu bringen, sie jedoch wachsen zu lassen, wenn sie größer als meine Mindestgröße ist.
Hamza Yerlikaya
Sie können dieses Verhalten haben, wenn Sie TableColumn.setMinWidth () anstelle von TableColumn.setMaxWidth () verwenden.
Akf
Um meinen letzten Kommentar zu ergänzen: Verwenden Sie TableColumn.setMinWidth () für jede Spalte in Ihrer Tabelle, einschließlich der letzten Spalte.
Akf
Das Einstellen der minimalen und maximalen Breite löste das Problem, aber jetzt fehlen Bildlaufleisten.
Hamza Yerlikaya
14

JTable.AUTO_RESIZE_LAST_COLUMNist definiert als "Bei allen Größenänderungsvorgängen nur Anpassungen an der letzten Spalte vornehmen", was bedeutet, dass Sie den automatischen Größenmodus am Ende Ihres Codes festlegen müssen , da sonst setPreferredWidth () keine Auswirkungen hat!

In Ihrem Fall wäre dies also der richtige Weg:

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
quelle
5

Verwenden Sie diese Methode

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

Oder erweitern Sie die JTableKlasse:

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

Und dann

table.setColumnWidths(30, 150, 100, 100);
Oleg Mikhailov
quelle
4

Lesen Sie die Bemerkung von Kleopatra (ihr zweites Mal schlug sie vor, sich javax.swing.JXTable anzuschauen , und jetzt tut es mir leid, dass ich das erste Mal nicht nachgesehen habe :)) Ich schlage vor, Sie folgen dem Link

Ich hatte diese Lösung für das gleiche Problem: (aber ich schlage vor, Sie folgen dem obigen Link) Skalieren Sie beim Ändern der Tabellengröße die Tabellenspaltenbreiten auf die aktuelle Gesamtbreite der Tabelle. Dazu verwende ich ein globales Int-Array für die (relativen) Spaltenbreiten:

private int[] columnWidths=null;

Ich benutze diese Funktion, um die Tabellenspaltenbreiten einzustellen:

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

}

Beim Einstellen der Daten rufe ich an:

    setColumnWidths(this.columnWidths);

und beim Ändern rufe ich den ComponentListener auf, der auf das übergeordnete Element der Tabelle festgelegt ist (in meinem Fall das JScrollPane, das der Container meiner Tabelle ist):

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

Beachten Sie, dass die JTable-Tabelle auch global ist:

private JTable table;

Und hier stelle ich den Hörer ein:

    scrollPane=new JScrollPane(table);
    scrollPane.addComponentListener(this);
michel.iamit
quelle
1
Soweit ich sehen kann, handelt es sich um einen (sehr spröden) Hack: Er wird nicht aktualisiert, wenn Benutzer eine Spaltenbreite ändern. Auch hier würde ich vorschlagen, dass Sie sich den Quellcode von JXTable ansehen - er hat eine zusätzliche Eigenschaft horizontalScroll, die das Füllen der verfügbaren Breite auslöst, wenn die Summe der Spalteneinstellungen kleiner als die aktuelle Breite ist, und ansonsten eine horizontale Bildlaufleiste
anzeigt
Ich weiß, dass es nicht darauf reagiert, dass der Benutzer die Tabellenbreiten manuell ändert. Auf diese Weise ist es ein Hack ... aber noch einmal: Es ist besser als oben vorgeschlagen. Aber du hast mich neugierig auf JXTable gemacht ... ich werde dort einen Blick darauf werfen! (und schön, wieder zu Ihnen auf einem Tisch Thema zu gehen :))
michel.iamit
Sie hatten Recht, sehen Sie meine Bemerkung über meiner Antwort, ich habe Ihre Bemerkung positiv bewertet!
michel.iamit
Zumindest war dies für mich nützlich, ich habe diesen Ansatz für meinen Fall mit einem Säulengewichtsprinzip verwendet.
Solostaran14
2
fireTableStructureChanged();

wird das Größenänderungsverhalten standardmäßig festlegen ! Wenn diese Methode irgendwo in Ihrem Code aufgerufen wird, nachdem Sie die Eigenschaften für die Spaltengröße festgelegt haben, werden alle Ihre Einstellungen zurückgesetzt. Diese Nebenwirkung kann indirekt auftreten. Fe als Folge der Änderung des verknüpften Datenmodells in einer Weise, wie diese Methode aufgerufen wird, nachdem Eigenschaften festgelegt wurden.

count0
quelle
1

Die Option ist nicht erforderlich. Stellen Sie einfach die bevorzugte Breite der letzten Spalte auf das Maximum ein, und es wird der gesamte zusätzliche Platz beansprucht.

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
quelle
0

Dieser Code funktioniert für mich ohne 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
quelle
-1

Verwenden Sie diesen Code. Es hat bei mir funktioniert. Ich habe über 3 Spalten nachgedacht. Ändern Sie den Schleifenwert für Ihren Code.

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
quelle