Configuración de Java JTable Ancho de columna

95

Tengo una JTable en la que configuro el tamaño de la columna de la siguiente manera:

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

Esto funciona bien, pero cuando la tabla está maximizada, obtengo un espacio vacío a la derecha de la última columna. ¿Es posible cambiar el tamaño de la última columna al final de la ventana cuando se cambia el tamaño?

Encontré una AUTO_RESIZE_LAST_COLUMNpropiedad en los documentos pero no funciona.

Editar: JTableestá en JScrollPanesu tamaño preferido.

Hamza Yerlikaya
fuente

Respuestas:

45

¿Qué sucede si llama setMinWidth(400)a la última columna en lugar de setPreferredWidth(400)?

En JavaDoc para JTable, lea los documentos con doLayout()mucho cuidado. Aquí hay algunas opciones:

Cuando se llama al método como resultado del cambio de tamaño de una ventana adjunta, resizingColumn es nulo. Esto significa que el cambio de tamaño se ha realizado "fuera" de JTable y el cambio, o "delta", debe distribuirse a todas las columnas independientemente del modo de cambio de tamaño automático de esta JTable.

Esta podría ser la razón por la AUTO_RESIZE_LAST_COLUMNque no te ayudó.

Nota: Cuando una JTable realiza ajustes en los anchos de las columnas, respeta absolutamente sus valores mínimo y máximo.

Esto dice que es posible que desee establecer Min == Max para todas las columnas excepto la última, luego establecer Min = Preferred en la última columna y no establecer Max o establecer un valor muy grande para Max.

Eddie
fuente
1
setMinWidth (400) todavía hace que la derecha de la tabla esté vacía
Hamza Yerlikaya
2
Intente agregar setMaxWidth (10000) para ver si eso hace una diferencia.
Eddie
1
Elimine la línea table.setAutoResizeMode (JTable.AUTO_RESIZE_OFF); Esto puede evitar el cambio de tamaño que desee.
Eddie
Es probable que también desea establecer min y el tamaño máximo en el propio JTable, si no lo ha hecho,
Eddie
3
Asegúrese de hacer la llamada setMinWidth después de aplicar el modelo de tabla ... Eso me hizo tropezar una vez por un tiempo.
Brian Knoblauch
23

Con JTable.AUTO_RESIZE_OFF, la tabla no cambiará el tamaño de ninguna de las columnas por usted, por lo que tomará su configuración preferida. Si su objetivo es que las columnas tengan el tamaño predeterminado de su preferencia, excepto para que la última columna llene el resto del panel, tiene la opción de usar JTable.AUTO_RESIZE_LAST_COLUMNautoResizeMode, pero podría ser más efectivo cuando se usa con en TableColumn.setMaxWidth()lugar de TableColumn. setPreferredWidth () para todas menos la última columna.

Una vez que esté satisfecho de que AUTO_RESIZE_LAST_COLUMNrealmente funciona, puede experimentar con una combinación de TableColumn.setMaxWidth()yTableColumn.setMinWidth()

akf
fuente
1
Cuando se usa AUTO_RESIZE_LAST_COLUMN, la tabla cambia de tamaño para que se ajuste al panel de desplazamiento, mi objetivo es tener la tabla en un cierto tamaño mínimo, pero hacerla crecer si es más grande que mi tamaño mínimo.
Hamza Yerlikaya
Puede tener este comportamiento si usa TableColumn.setMinWidth () en lugar de TableColumn.setMaxWidth ().
akf
para agregar a mi último comentario: use TableColumn.setMinWidth () para cada columna de su tabla, incluida la última columna.
akf
configurar el ancho mínimo y máximo resolvió el problema, pero ahora faltan las barras de desplazamiento.
Hamza Yerlikaya
15

JTable.AUTO_RESIZE_LAST_COLUMNse define como "Durante todas las operaciones de cambio de tamaño, aplique ajustes solo a la última columna", lo que significa que debe establecer el modo de tamaño automático al final de su código , de lo contrario, setPreferredWidth () no afectará nada.

Entonces, en su caso, esta sería la forma correcta:

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

Usa este método

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

O ampliar la JTableclase:

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

Y entonces

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

Al leer el comentario de Kleopatra (la segunda vez que sugirió echar un vistazo a javax.swing.JXTable , y ahora lamento no haberlo visto la primera vez :)) te sugiero que sigas el enlace

Tuve esta solución para el mismo problema: (pero le sugiero que siga el enlace de arriba) Al cambiar el tamaño de la tabla, escale el ancho de la columna de la tabla al ancho total de la tabla actual. para hacer esto, uso una matriz global de entradas para los anchos de columna (relativos)):

private int[] columnWidths=null;

Utilizo esta función para establecer los anchos de columna de la tabla:

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

}

Al configurar los datos, llamo:

    setColumnWidths(this.columnWidths);

y al cambiar, llamo al ComponentListener establecido en el padre de la tabla (en mi caso, el JScrollPane que es el contenedor de mi tabla):

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

tenga en cuenta que la tabla JTable también es global:

private JTable table;

Y aquí configuro el oyente:

    scrollPane=new JScrollPane(table);
    scrollPane.addComponentListener(this);
michel.iamit
fuente
1
Por lo que puedo ver, este es un truco (muy frágil): no se actualiza cuando el usuario cambia el ancho de una columna. Nuevamente, le sugiero que consulte el código fuente de JXTable: tiene una propiedad adicional horizontalScroll que activa el llenado del ancho disponible si la suma de las preferencias de la columna es menor que el ancho actual y muestra una barra de desplazamiento horizontal de lo contrario
kleopatra
Sé que no reacciona cuando el usuario cambia el ancho de la tabla manualmente, de esa manera es un truco ... pero nuevamente: es mejor que lo sugerido anteriormente. Pero me hiciste sentir curiosidad por JXTable ... ¡echaré un vistazo allí! (y es bueno volver a
hablar
Tenías razón, mira mi comentario además de mi respuesta, ¡voté a favor de tu comentario!
michel.iamit
Al menos esto fue útil para mí, utilicé este enfoque para mi caso con un principio de peso de columna.
Solostaran 14 de
2
fireTableStructureChanged();

por defecto el comportamiento de cambio de tamaño ! Si se llama a este método en algún lugar de su código DESPUÉS de que haya configurado las propiedades de cambio de tamaño de la columna, se restablecerán todas sus configuraciones. Este efecto secundario puede ocurrir indirectamente. Fe como consecuencia del cambio del modelo de datos vinculados de una manera que se llama a este método, después de que se establecen las propiedades.

count0
fuente
1

No es necesaria la opción, simplemente haga que el ancho preferido de la última columna sea el máximo y ocupará todo el espacio adicional.

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

Este código me funcionó sin 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
fuente
-1

Utilice este código. Funcionó para mí. Consideré 3 columnas. Cambie el valor del bucle de su código.

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
fuente