Java JTable paramètre Largeur de colonne

95

J'ai un JTable dans lequel je définis la taille de la colonne comme suit:

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

Cela fonctionne bien, mais lorsque la table est agrandie, j'obtiens un espace vide à droite de la dernière colonne. Est-il possible de redimensionner la dernière colonne à la fin de la fenêtre une fois redimensionnée?

J'ai trouvé une AUTO_RESIZE_LAST_COLUMNpropriété dans les documents mais cela ne fonctionne pas.

Edit: JTableest dans une JScrollPanesa taille préférée est définie.

Hamza Yerlikaya
la source

Réponses:

45

Que se passe-t-il si vous appelez setMinWidth(400)sur la dernière colonne au lieu de setPreferredWidth(400)?

Dans le JavaDoc pour JTable, lisez doLayout()très attentivement la documentation. Voici quelques bits de choix:

Lorsque la méthode est appelée à la suite du redimensionnement d'une fenêtre englobante, resizingColumn est null. Cela signifie que le redimensionnement a eu lieu "en dehors" du JTable et le changement - ou "delta" - doit être distribué à toutes les colonnes quel que soit le mode de redimensionnement automatique de ce JTable.

Cela pourrait expliquer pourquoi AUTO_RESIZE_LAST_COLUMNne vous a pas aidé.

Remarque: Lorsqu'un JTable ajuste la largeur des colonnes, il respecte absolument leurs valeurs minimales et maximales.

Cela indique que vous souhaiterez peut-être définir Min == Max pour toutes les colonnes sauf les dernières, puis définir Min = Preferred sur la dernière colonne et ne pas définir Max ou définir une très grande valeur pour Max.

Eddie
la source
1
setMinWidth (400) fait toujours que la droite de la table est vide
Hamza Yerlikaya
2
Essayez d'ajouter setMaxWidth (10000) pour voir si cela fait une différence.
Eddie le
1
Supprimez la ligne table.setAutoResizeMode (JTable.AUTO_RESIZE_OFF); Cela peut empêcher le redimensionnement souhaité.
Eddie
Vous voudrez probablement aussi définir la taille minimale et maximale sur le JTable lui-même, si vous ne l'avez pas déjà fait,
Eddie
3
Assurez-vous de faire l'appel setMinWidth après avoir appliqué le modèle de table ... Cela m'a fait trébucher une fois pendant un certain temps.
Brian Knoblauch
23

Avec JTable.AUTO_RESIZE_OFF, le tableau ne changera pas la taille de l'une des colonnes pour vous, il prendra donc votre paramètre préféré. Si votre objectif est d'avoir les colonnes par défaut à votre taille préférée, sauf pour que la dernière colonne remplisse le reste du volet, vous avez la possibilité d'utiliser l' JTable.AUTO_RESIZE_LAST_COLUMNautoResizeMode, mais il peut être plus efficace lorsqu'il est utilisé avec TableColumn.setMaxWidth()au lieu de TableColumn. setPreferredWidth () pour tout sauf la dernière colonne.

Une fois que vous êtes convaincu que AUTO_RESIZE_LAST_COLUMNcela fonctionne, vous pouvez expérimenter une combinaison de TableColumn.setMaxWidth()etTableColumn.setMinWidth()

akf
la source
1
Lorsque AUTO_RESIZE_LAST_COLUMN est utilisé, la table est redimensionnée pour s'adapter au volet de défilement, mon objectif est d'avoir la table à une certaine taille minimale mais de la faire grandir si elle est plus grande que ma taille minimale.
Hamza Yerlikaya
Vous pouvez avoir ce comportement si vous utilisez TableColumn.setMinWidth () au lieu de TableColumn.setMaxWidth ().
akf
pour ajouter à mon dernier commentaire: utilisez TableColumn.setMinWidth () pour chaque colonne de votre tableau, y compris la dernière colonne.
akf
le réglage de la largeur minimale et maximale a résolu le problème, mais maintenant les barres de défilement sont manquantes.
Hamza Yerlikaya
15

JTable.AUTO_RESIZE_LAST_COLUMNest défini comme "Pendant toutes les opérations de redimensionnement, n'appliquez les ajustements qu'à la dernière colonne" ce qui signifie que vous devez définir le mode de redimensionnement automatique à la fin de votre code , sinon setPreferredWidth () n'affectera rien!

Donc, dans votre cas, ce serait la bonne façon:

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
la source
5

Utilisez cette méthode

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

Ou prolongez la JTableclasse:

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

Puis

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

En lisant la remarque de Kleopatra (sa deuxième fois, elle a suggéré de jeter un œil à javax.swing.JXTable , et maintenant je suis désolé de ne pas avoir jeté un coup d'œil la première fois :)) Je vous suggère de suivre le lien

J'ai eu cette solution pour le même problème: (mais je vous suggère de suivre le lien ci-dessus) Lors du redimensionnement du tableau, mettez à l'échelle les largeurs de colonne du tableau à la largeur totale du tableau actuel. pour ce faire, j'utilise un tableau global d'entiers pour les largeurs de colonne (relatives)):

private int[] columnWidths=null;

J'utilise cette fonction pour définir les largeurs de colonne du tableau:

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

}

Lors de la configuration des données que j'appelle:

    setColumnWidths(this.columnWidths);

et en changeant, j'appelle le jeu ComponentListener au parent de la table (dans mon cas le JScrollPane qui est le conteneur de ma table):

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

notez que la table JTable est également globale:

private JTable table;

Et ici, je règle l'auditeur:

    scrollPane=new JScrollPane(table);
    scrollPane.addComponentListener(this);
michel.iamit
la source
1
pour autant que je puisse voir, c'est un hack (très fragile): il ne se met pas à jour lorsque l'utilisateur change la largeur d'une colonne. Encore une fois, je vous suggère de regarder dans le code source de JXTable - il a une propriété supplémentaire horizontalScroll qui déclenche le remplissage de la largeur disponible si la somme des préférences de colonne est inférieure à la largeur actuelle et affiche une barre de défilement horizontale sinon
kleopatra
Je sais que cela ne réagit pas au fait que l'utilisateur change manuellement les largeurs de table, de cette façon c'est un hack ... mais encore une fois: c'est mieux que suggéré ci-dessus. Mais vous m'avez rendu curieux de JXTable .... Je vais y jeter un œil! (et agréable de revenir avec vous sur un sujet de table :))
michel.iamit
Vous aviez raison, voyez ma remarque en plus de ma réponse, j'ai voté pour votre remarque!
michel.iamit
Au moins cela a été utile pour moi, j'ai utilisé cette approche pour mon cas avec un principe de poids de colonne.
Solostaran14
2
fireTableStructureChanged();

sera le comportement de redimensionnement par défaut ! Si cette méthode est appelée quelque part dans votre code APRÈS avoir défini les propriétés de redimensionnement de la colonne, tous vos paramètres seront réinitialisés. Cet effet secondaire peut survenir indirectement. Fe à la suite de la modification du modèle de données lié d'une manière que cette méthode est appelée, une fois les propriétés définies.

count0
la source
1

Pas besoin de l'option, faites simplement la largeur préférée de la dernière colonne au maximum et cela prendra tout l'espace supplémentaire.

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
la source
0

Ce code fonctionne pour moi sans 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
la source
-1

Utilisez ce code. Cela a fonctionné pour moi. J'ai envisagé 3 colonnes. Modifiez la valeur de boucle de votre 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
la source