Search code examples
javaswingjtablejtableheader

Dynamic Change JTable Header


I have a table displaying data for a year. The table can have different periods for each column, e.g. weeks, bi-weeks, months. I wish to change the year being displayed. I have managed to get the table data and header to change, however, the structure of the table is lost.

The table is set up by this:

public class GenerateTable extends JTable {
private class RenderSelect extends JComponent implements TableCellRenderer {

    @Override
    public Component getTableCellRendererComponent(JTable table,
            Object value, boolean isSelected, boolean hasFocus, int row,
            int column) {
        if ((row & 1)==0) {
            JCheckBox boxTemp = new JCheckBox();
            boxTemp.setSelected((boolean)value);
            return boxTemp;
        }
        else
            return new JTextField(" ");
    }

}
RenderSelect objRender = new RenderSelect();
public GenerateTable(GenerateTableModel model) {
    super(model);
    this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    /*
     * Select
     */
    TableColumn colSelect = this.getColumnModel().getColumn(0);
    colSelect.setPreferredWidth(70);
    colSelect.setMinWidth(40);
    colSelect.setCellRenderer(objRender);
    colSelect.setCellEditor(new DefaultCellEditor(new JCheckBox()));
    /*
     * category
     */
    this.getColumnModel().getColumn(1).setResizable(false);
    this.getColumnModel().getColumn(1).setPreferredWidth(200);
    this.getColumnModel().getColumn(1).setMinWidth(100);
    /*
     * Amount values
     */
    for (int i=2;i<model.getColumnCount();i++) {
        colSelect = this.getColumnModel().getColumn(i);
        colSelect.setPreferredWidth(80);
        colSelect.setMinWidth(80);
        colSelect.setResizable(false);
    }
    setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
}

}

it gives me a layout like this:

enter image description here

I have the following code to change the year:

private void changeYears() {
    modGen.setYear(boxYears.getSelectedIndex()+1);
    modGen.fireTableStructureChanged();
    panMid.revalidate();
}

The table model (modGen) takes the year and returns the appropriate data in getColumnName and getValueAt based on the year.

When I use this the result is:

enter image description here

The table column widths are lost and the renderer for column 0 seems to have been dropped. If I use fireTableDataChanged the header does not change but the data does. Using fireTableStructureChanged does change the header but looses the structure as stated.

Any ideas?


Solution

  • You must update the column model on changing header value

    JTable table = new JTable(modGen);
    
    //...
    
    modGen.setYear(boxYears.getSelectedIndex()+1);
    for (int i = 0; i < modGen.getColumnCount(); i++) {
      String name = modGen.getColumnName(i);
      int viewIdx = table.convertColumnIndexToView(i);
      if (viewIdx >= 0) {
        table.getColumnModel().getColumn(viewIdx).setHeaderValue(name);
      }
    }