Adjust columns according to available Jtable size

Asked

Viewed 1,973 times

2

I have a JTable where the user can hide and then re-display one or more columns.
I found a code at this link which adjusts the column according to the size of the "field value". I call this method as soon as I populate the JTable.

public void defaultSize(JTable table) {
     final TableColumnModel columnModel = table.getColumnModel();
    for (int column = 0; column < table.getColumnCount(); column++) {
        int width = 250;
        for (int row = 0; row < table.getRowCount(); row++) {
            TableCellRenderer renderer = table.getCellRenderer(row, column);
            Component comp = table.prepareRenderer(renderer, row, column);
            width = Math.max(comp.getPreferredSize().width + 1, width);
            columnModel.getColumn(column).setPreferredWidth(width);
        }

    }

At the event of JRadioButton, where the user hides or shows the column again, I have this code:

private void jRadioCodigoItemStateChanged(java.awt.event.ItemEvent evt) {                                              
        int width = 80;
        if (evt.getStateChange() == ItemEvent.DESELECTED) {
            jTableResultado.getColumnModel().getColumn(0).setMinWidth(0);
            jTableResultado.getColumnModel().getColumn(0).setMaxWidth(0);
            jTableResultado.getColumnModel().getColumn(0).setWidth(0);
            jTableResultado.getColumnModel().getColumn(0).setPreferredWidth(0);
            defaultSize();
        } else if (evt.getStateChange() == ItemEvent.SELECTED) {
            jTableResultado.getColumnModel().getColumn(0).setMinWidth(width);
            jTableResultado.getColumnModel().getColumn(0).setMaxWidth(width);
            jTableResultado.getColumnModel().getColumn(0).setWidth(width);
            jTableResultado.getColumnModel().getColumn(0).setPreferredWidth(width);
             defaultSize();
        }

    } 

What I wanted now was that when hidden a column, the rest of the columns would be adjusted according to the remaining size of the JTable, so that it does not occur as the image below shows. And also that, instead of passing the value to the column size, by displaying it again in the jRadioButton, that was adjusted according to the size of the field value, the same occurs when I call the method defaultSize() (I only get this by loading the table the first time).

inserir a descrição da imagem aqui

Reduced example of code:

import java.awt.Component;
import java.awt.event.ItemEvent;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

/**
 *
 * @author LockDown
 */
public final class NovoJFrame extends javax.swing.JFrame {

    /**
     * Creates new form NovoJFrame
     */
    public NovoJFrame() {
        initComponents();
        loadtable();
    }

    public void loadtable() {
        DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
        model.setNumRows(0);
        model.addRow(new Object[]{"Rodrigo", "32", "Masculino"});
        model.addRow(new Object[]{"Elza", "32", "Feminino"});
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jRadioButton1 = new javax.swing.JRadioButton();
        jRadioButton2 = new javax.swing.JRadioButton();
        jRadioButton3 = new javax.swing.JRadioButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jTable1.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null},
                {null, null, null},
                {null, null, null},
                {null, null, null}
            },
            new String [] {
                "Nome", "Idade", "Sexo"
            }
        ));
        jScrollPane1.setViewportView(jTable1);

        jRadioButton1.setText("Nome");
        jRadioButton1.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                jRadioButton1ItemStateChanged(evt);
            }
        });

        jRadioButton2.setText("Idade");
        jRadioButton2.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                jRadioButton2ItemStateChanged(evt);
            }
        });

        jRadioButton3.setText("Sexo");
        jRadioButton3.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                jRadioButton3ItemStateChanged(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(292, 292, 292)
                        .addComponent(jRadioButton1)
                        .addGap(18, 18, 18)
                        .addComponent(jRadioButton2)
                        .addGap(18, 18, 18)
                        .addComponent(jRadioButton3)
                        .addGap(0, 375, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jRadioButton1)
                    .addComponent(jRadioButton2)
                    .addComponent(jRadioButton3))
                .addContainerGap(24, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        

    private void jRadioButton1ItemStateChanged(java.awt.event.ItemEvent evt) {                                               
        int width = 100;
        if (evt.getStateChange() == ItemEvent.SELECTED) {
            jTable1.getColumnModel().getColumn(0).setMinWidth(0);
            jTable1.getColumnModel().getColumn(0).setMaxWidth(0);
            jTable1.getColumnModel().getColumn(0).setWidth(0);
            jTable1.getColumnModel().getColumn(0).setPreferredWidth(0);
            defaultSize(jTable1);
            jTable1.revalidate();

        } else if (evt.getStateChange() == ItemEvent.DESELECTED) {
            jTable1.getColumnModel().getColumn(0).setMinWidth(width);
            jTable1.getColumnModel().getColumn(0).setMaxWidth(width);
            jTable1.getColumnModel().getColumn(0).setWidth(width);
            jTable1.getColumnModel().getColumn(0).setPreferredWidth(width);
            defaultSize(jTable1);
            jTable1.revalidate();

        }
    }                                              

    private void jRadioButton2ItemStateChanged(java.awt.event.ItemEvent evt) {                                               
        int width = 100;
        if (evt.getStateChange() == ItemEvent.SELECTED) {
            jTable1.getColumnModel().getColumn(1).setMinWidth(0);
            jTable1.getColumnModel().getColumn(1).setMaxWidth(0);
            jTable1.getColumnModel().getColumn(1).setWidth(0);
            jTable1.getColumnModel().getColumn(1).setPreferredWidth(0);
            defaultSize(jTable1);
            jTable1.revalidate();

        } else if (evt.getStateChange() == ItemEvent.DESELECTED) {
            jTable1.getColumnModel().getColumn(1).setMinWidth(width);
            jTable1.getColumnModel().getColumn(1).setMaxWidth(width);
            jTable1.getColumnModel().getColumn(1).setWidth(width);
            jTable1.getColumnModel().getColumn(1).setPreferredWidth(width);
            defaultSize(jTable1);
            jTable1.revalidate();

        }
    }                                              

    private void jRadioButton3ItemStateChanged(java.awt.event.ItemEvent evt) {                                               
        int width = 100;
        if (evt.getStateChange() == ItemEvent.SELECTED) {
            jTable1.getColumnModel().getColumn(2).setMinWidth(0);
            jTable1.getColumnModel().getColumn(2).setMaxWidth(0);
            jTable1.getColumnModel().getColumn(2).setWidth(0);
            jTable1.getColumnModel().getColumn(2).setPreferredWidth(0);
            defaultSize(jTable1);
            jTable1.revalidate();

        } else if (evt.getStateChange() == ItemEvent.DESELECTED) {
            jTable1.getColumnModel().getColumn(2).setMinWidth(width);
            jTable1.getColumnModel().getColumn(2).setMaxWidth(width);
            jTable1.getColumnModel().getColumn(2).setWidth(width);
            jTable1.getColumnModel().getColumn(2).setPreferredWidth(width);
            defaultSize(jTable1);
            jTable1.revalidate();

        }
    }                                              
    public void defaultSize(JTable table) {
       final TableColumnModel columnModel = table.getColumnModel();
        for (int column = 0; column < table.getColumnCount(); column++) {
            int width = 250;
            for (int row = 0; row < table.getRowCount(); row++) {
                TableCellRenderer renderer = table.getCellRenderer(row, column);
                Component comp = table.prepareRenderer(renderer, row, column);
                width = Math.max(comp.getPreferredSize().width + 1, width);
                columnModel.getColumn(column).setPreferredWidth(width);
            }

        }
    }


    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(NovoJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(NovoJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(NovoJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(NovoJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new NovoJFrame().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JRadioButton jRadioButton1;
    private javax.swing.JRadioButton jRadioButton2;
    private javax.swing.JRadioButton jRadioButton3;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable1;
    // End of variables declaration                   
}
  • Try to run jTableResultado.revalidade(); shortly after defaultSize(); in the method jRadioCodigoItemStateChanged, to see if the table updates.

  • @diegofm added an "example" of code, for a better understanding of the context. o Revalidate() had no effect.

  • Did you turn off the autoresize of jtable ne? x It is not possible to simulate the problem, do not have the initicomponents method in the code.

  • Yes, I turned it off. I added the code again.

1 answer

2


After analyzing your code, I realized that the JTable uses as the maximum value of width of each column the value of Integer.MAX_VALUE(you must be creating by GUI-Builder, therefore this behavior), which represents the maximum value of an integer. When you reset all column width information, you end up losing this feature, because the maximum value will be the one you set again, and in the code you are setting to 100.

To try to work around this, I have created a method for the part where you will resize the columns, according to the selection of JRadioButton:

private void resizeWidthColumn(int indexColumn, int widthColumn) {
    jTable1.getColumnModel().getColumn(indexColumn).setMinWidth(widthColumn);
    jTable1.getColumnModel().getColumn(indexColumn).setMaxWidth(widthColumn == 0 ? widthColumn : Integer.MAX_VALUE);
    jTable1.getColumnModel().getColumn(indexColumn).setWidth(widthColumn);
    jTable1.getColumnModel().getColumn(indexColumn).setPreferredWidth(widthColumn);
}

and within the ItemListener of JRadioButtons, called this method with value that you were passing on condition:

private void jRadioButton1ItemStateChanged(java.awt.event.ItemEvent evt) {
    int widthColumn = 100;
    if (evt.getStateChange() == ItemEvent.SELECTED) {
        resizeWidthColumn(0, 0);
        defaultSize(jTable1);

    } else if (evt.getStateChange() == ItemEvent.DESELECTED) {
        resizeWidthColumn(0, widthColumn);
        defaultSize(jTable1);
    }
}

private void jRadioButton2ItemStateChanged(java.awt.event.ItemEvent evt) {
    int widthColumn = 100;
    if (evt.getStateChange() == ItemEvent.SELECTED) {
        resizeWidthColumn(1, 0);;
        defaultSize(jTable1);

    } else if (evt.getStateChange() == ItemEvent.DESELECTED) {
        resizeWidthColumn(1, widthColumn);
        defaultSize(jTable1);

    }
}

private void jRadioButton3ItemStateChanged(java.awt.event.ItemEvent evt) {
    int widthColumn = 100;
    if (evt.getStateChange() == ItemEvent.SELECTED) {
        resizeWidthColumn(2, 0);
        defaultSize(jTable1);

    } else if (evt.getStateChange() == ItemEvent.DESELECTED) {
        resizeWidthColumn(2, widthColumn);
        defaultSize(jTable1);
    }
}

Note that in setMaxWidth(), I made a small condition, and it is this condition that was decisive to resume the previous maximum value of the column, which was INTEGER.MAX_VALUE, case JRadioButton is being unchecked, and zero if it is being marked.

With this solution, it is not necessary (and according to the tests I did, it would not be recommended) to change the default resize mode (autoReziseMode) JTable, as it may cause unwanted resizing.

With this, the final code (and testable code made using the netbeans GUI-Builder) got this way:

import java.awt.Component;
import java.awt.event.ItemEvent;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;

public final class NovoJFrame extends javax.swing.JFrame {

    public NovoJFrame() {
        initComponents();
        loadtable();
    }

    public void loadtable() {
        DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
        model.setNumRows(0);
        model.addRow(new Object[]{"Rodrigo", "32", "Masculino"});
        model.addRow(new Object[]{"Elza", "32", "Feminino"});
    }

    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jRadioButton1 = new javax.swing.JRadioButton();
        jRadioButton2 = new javax.swing.JRadioButton();
        jRadioButton3 = new javax.swing.JRadioButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jTable1.setModel(new javax.swing.table.DefaultTableModel(
                new Object[][]{
                    {null, null, null},
                    {null, null, null},
                    {null, null, null},
                    {null, null, null}
                },
                new String[]{
                    "Nome", "Idade", "Sexo"
                }
        ));
        jScrollPane1.setViewportView(jTable1);

        jRadioButton1.setText("Nome");
        jRadioButton1.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                jRadioButton1ItemStateChanged(evt);
            }
        });

        jRadioButton2.setText("Idade");
        jRadioButton2.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                jRadioButton2ItemStateChanged(evt);
            }
        });

        jRadioButton3.setText("Sexo");
        jRadioButton3.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                jRadioButton3ItemStateChanged(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(jScrollPane1)
                                .addGroup(layout.createSequentialGroup()
                                        .addGap(292, 292, 292)
                                        .addComponent(jRadioButton1)
                                        .addGap(18, 18, 18)
                                        .addComponent(jRadioButton2)
                                        .addGap(18, 18, 18)
                                        .addComponent(jRadioButton3)
                                        .addGap(0, 375, Short.MAX_VALUE)))
                        .addContainerGap())
        );
        layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(jRadioButton1)
                                .addComponent(jRadioButton2)
                                .addComponent(jRadioButton3))
                        .addContainerGap(24, Short.MAX_VALUE))
        );

        pack();
    }                      

    private void jRadioButton1ItemStateChanged(java.awt.event.ItemEvent evt) {
        int widthColumn = 100;
        if (evt.getStateChange() == ItemEvent.SELECTED) {
            resizeWidthColumn(0, 0);
            defaultSize(jTable1);

        } else if (evt.getStateChange() == ItemEvent.DESELECTED) {
            resizeWidthColumn(0, widthColumn);
            defaultSize(jTable1);
        }
    }

    private void jRadioButton2ItemStateChanged(java.awt.event.ItemEvent evt) {
        int widthColumn = 100;
        if (evt.getStateChange() == ItemEvent.SELECTED) {
            resizeWidthColumn(1, 0);;
            defaultSize(jTable1);

        } else if (evt.getStateChange() == ItemEvent.DESELECTED) {
            resizeWidthColumn(1, widthColumn);
            defaultSize(jTable1);

        }
    }

    private void jRadioButton3ItemStateChanged(java.awt.event.ItemEvent evt) {
        int widthColumn = 100;
        if (evt.getStateChange() == ItemEvent.SELECTED) {
            resizeWidthColumn(2, 0);
            defaultSize(jTable1);

        } else if (evt.getStateChange() == ItemEvent.DESELECTED) {
            resizeWidthColumn(2, widthColumn);
            defaultSize(jTable1);
        }
    }

    private void resizeWidthColumn(int indexColumn, int widthColumn) {
        jTable1.getColumnModel().getColumn(indexColumn).setMinWidth(widthColumn);
        jTable1.getColumnModel().getColumn(indexColumn).setMaxWidth(widthColumn == 0 ? widthColumn : Integer.MAX_VALUE);
        jTable1.getColumnModel().getColumn(indexColumn).setWidth(widthColumn);
        jTable1.getColumnModel().getColumn(indexColumn).setPreferredWidth(widthColumn);
    }

    public void defaultSize(JTable table) {

        final TableColumnModel columnModel = table.getColumnModel();
        for (int column = 0; column < table.getColumnCount(); column++) {
            int width = 250;
            for (int row = 0; row < table.getRowCount(); row++) {
                TableCellRenderer renderer = table.getCellRenderer(row, column);
                Component comp = table.prepareRenderer(renderer, row, column);
                width = Math.max(comp.getPreferredSize().width + 1, width);
            }
            columnModel.getColumn(column).setPreferredWidth(width);
        }
    }

    public static void main(String args[]) {

        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(NovoJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(NovoJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(NovoJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(NovoJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }

        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new NovoJFrame().setVisible(true);
                System.out.println(Integer.MAX_VALUE);
            }
        });
    }

    private javax.swing.JRadioButton jRadioButton1;
    private javax.swing.JRadioButton jRadioButton2;
    private javax.swing.JRadioButton jRadioButton3;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable1;

}

Demonstration of operation:

gif animado com o funcionamento do redimensionamento

You can unify these three methods of JRadioButton, who do the same thing, passing only the column index, but it was not part of the doubt, I preferred not to change the code more than it was necessary.

  • I’ll try to adjust my codes here, thanks for now.

  • So it worked, though, I got strings well extended in jTable, thus the value appears incomplete, due to having removed the jTable1.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); code. I’m trying to solve, but so far nothing.

  • @Rodrigo does not want to complicate your project, but maybe it is a better alternative to create a cellrenderer and apply a Jtextarea to these cells that have a very large text, because then you can break lines and display them without having to keep sizing the table. Imagine if the strings, with combined size, become disproportionate to the monitor?

  • Disproportionate to the monitor will not, but will get larger than the space to which it is being divided at the moment.

  • Actually there are 17 columns, this is the problem, to be clear, so the space for each one after resizing the jTable is small for each column.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.