Configuração Java JTable da largura da coluna

95

Eu tenho uma JTable na qual defino o tamanho da coluna da seguinte maneira:

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

Isso funciona bem, mas quando a tabela é maximizada, recebo um espaço vazio à direita da última coluna. É possível redimensionar a última coluna para o final da janela quando redimensionada?

Encontrei um AUTO_RESIZE_LAST_COLUMNimóvel no docs, mas não funciona.

Editar: JTableestá em um JScrollPanetamanho de sua preferência definido.

Hamza Yerlikaya
fonte

Respostas:

45

O que acontece se você chamar setMinWidth(400)na última coluna em vez de setPreferredWidth(400)?

No JavaDoc para JTable, leia os documentos para com doLayout()muito cuidado. Aqui estão alguns bits de escolha:

Quando o método é chamado como resultado do redimensionamento de uma janela envolvente, o resizingColumn é nulo. Isso significa que o redimensionamento ocorreu "fora" do JTable e a alteração - ou "delta" - deve ser distribuída para todas as colunas, independentemente do modo de redimensionamento automático deste JTable.

Pode ser por isso AUTO_RESIZE_LAST_COLUMNque não o ajudou.

Nota: Quando uma JTable faz ajustes nas larguras das colunas, ela respeita seus valores mínimo e máximo de forma absoluta.

Isso indica que você pode querer definir Min == Max para todas as colunas, exceto as últimas, então definir Min = Preferred na última coluna e não definir Max ou definir um valor muito grande para Max.

Eddie
fonte
1
setMinWidth (400) ainda faz com que a direita da tabela fique vazia
Hamza Yerlikaya
2
Experimente adicionar setMaxWidth (10000) para ver se isso faz diferença.
Eddie
1
Remova a linha table.setAutoResizeMode (JTable.AUTO_RESIZE_OFF); Isso pode impedir o redimensionamento que você deseja.
Eddie
Você provavelmente também deseja definir o tamanho mínimo e máximo no próprio JTable, se ainda não o fez,
Eddie
3
Certifique-se de fazer a chamada setMinWidth após aplicar o modelo de tabela ... Isso me tropeçou uma vez por um tempo.
Brian Knoblauch
23

Com JTable.AUTO_RESIZE_OFF, a tabela não alterará o tamanho de nenhuma das colunas para você, portanto, assumirá sua configuração preferida. Se o seu objetivo é que as colunas tenham o tamanho padrão de sua preferência, exceto que a última coluna preencha o resto do painel, você tem a opção de usar o JTable.AUTO_RESIZE_LAST_COLUMNautoResizeMode, mas pode ser mais eficaz quando usado com em TableColumn.setMaxWidth()vez de TableColumn. setPreferredWidth () para todas, exceto a última coluna.

Quando estiver satisfeito com o que de AUTO_RESIZE_LAST_COLUMNfato funciona, você pode experimentar uma combinação de TableColumn.setMaxWidth()eTableColumn.setMinWidth()

akf
fonte
1
Quando AUTO_RESIZE_LAST_COLUMN é usado, a tabela é redimensionada para caber no painel de rolagem, meu objetivo é ter a tabela em um determinado tamanho mínimo, mas fazê-la crescer se for maior do que meu tamanho mínimo.
Hamza Yerlikaya
Você pode ter esse comportamento se usar TableColumn.setMinWidth () em vez de TableColumn.setMaxWidth ().
akf
para adicionar ao meu último comentário: use TableColumn.setMinWidth () para cada coluna em sua tabela, incluindo a última coluna.
akf
definir a largura mínima e máxima resolveu o problema, mas agora as barras de rolagem estão faltando.
Hamza Yerlikaya
14

JTable.AUTO_RESIZE_LAST_COLUMNé definido como "Durante todas as operações de redimensionamento, aplique ajustes apenas à última coluna", o que significa que você deve definir o modo automático no final do seu código , caso contrário setPreferredWidth () não afetará nada!

Portanto, no seu caso, esta seria a maneira correta:

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

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

Ou estenda a JTableaula:

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

E depois

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

Lendo a observação do Kleopatra (na segunda vez, ela sugeriu dar uma olhada em javax.swing.JXTable , e agora sinto muito não ter dado uma olhada na primeira vez :)) Sugiro que você siga o link

Eu tinha essa solução para o mesmo problema: (mas sugiro que você siga o link acima) Ao redimensionar a tabela, dimensione as larguras das colunas da tabela para a largura total da tabela atual. para fazer isso, uso uma matriz global de ints para as larguras de coluna (relativas)):

private int[] columnWidths=null;

Eu uso esta função para definir as larguras das colunas da tabela:

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

}

Ao definir os dados, eu chamo:

    setColumnWidths(this.columnWidths);

e ao mudar eu chamo o ComponentListener definido para o pai da tabela (no meu caso o JScrollPane que é o contêiner da minha tabela):

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

observe que a tabela JTable também é global:

private JTable table;

E aqui eu defino o ouvinte:

    scrollPane=new JScrollPane(table);
    scrollPane.addComponentListener(this);
michel.iamit
fonte
1
até onde posso ver, este é um hack (muito frágil): ele não atualiza quando o usuário altera a largura da coluna. Novamente, eu sugiro que você olhe para o código-fonte de JXTable - ele tem uma propriedade adicional horizontalScroll que dispara o preenchimento da largura disponível se a soma das preferências de coluna for menor que a largura atual e mostra uma barra de rolagem horizontal de outra forma
kleopatra
Eu sei que não reage ao usuário mudar a largura da mesa manualmente, dessa forma é um hack ... mas novamente: é melhor do que o sugerido acima. Mas você me deixou curioso para JXTable .... Vou dar uma olhada lá! (e bom
falar
Você estava certo, veja meu comentário além da minha resposta, eu votei a favor de seu comentário!
michel.iamit
Pelo menos isso foi útil para mim, usei essa abordagem para meu caso com um princípio de peso de coluna.
Solostaran14
2
fireTableStructureChanged();

irá padronizar o comportamento de redimensionamento ! Se este método for chamado em algum lugar do seu código DEPOIS de você definir as propriedades de redimensionamento da coluna, todas as suas configurações serão redefinidas. Este efeito colateral pode acontecer indiretamente. Fe como consequência do modelo de dados vinculado ser alterado de uma forma que este método é chamado, após as propriedades serem definidas.

contagem0
fonte
1

Não há necessidade da opção, apenas faça com que a largura preferida da última coluna seja a máxima e ela ocupará todo o espaço extra.

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

Este código funcionou para mim sem 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
fonte
-1

Use este código. Funcionou para mim Eu considerei por 3 colunas. Altere o valor do loop para o seu 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
fonte