I'm developing a Java app to display and edit a Judging Schedule Table for car shows. In this Table each row represents a Timeslot, and each column represents a judge. The contents of Cell(ts, j) is a text string with the car ID and owner ID. Since each car will have either 2 or 3 judges, there will be 2 or 3 cells in each row for each car being judged in that timeslot. Also, there may be several cars judged simultaneously so long as judges are not assigned.
The assignments of judges to cars and cars to timeslots is a very complex problem, and is generated outside the context of my app. IOW, I can read the initial assignments from a file and populate the table Header and RowData for a Swing JTable. At this point my app does that just fine. The purpose of my app is to allow adjustments to the Judging Schedule Table in the field, the morning of the show. For example, a judge might not show up, or the Chief judge might want to move a car to a different timeslot. So, in addition to a File Open menu item, the app will have editing options such as "Move Entry," and "Change Judge".
Note, however, that any such changes have to obey certain rules such as not expecting judges to be judging two cars at the same time, etc. This means I can't just have the user editing the displayed directly. Consequently, the approach I have taken is to have methods that change the data from which the table is constructed, then use it to reconstruct the table exactly the way it was constructed in the first place.
With that background, here's my problem: The displayed table doesn't change. Here's the Update Table method that is used after the data is first created, and again after any editing. Here's a zippd JAR file. This is a simplified version BTW, I'm working in Netbeans.
public void updateScheduleTable(){
scheduletable = new javax.swing.JTable();
schedulescrollpane = new javax.swing.JScrollPane();
scheduletable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
List<ConcoursTestModel.TableColHeader> headerList;
//
// The schedule table header items must be extracted from theConcoursModel
//
headerList = theConcoursModel.UpdateScheduleTableHeader();
// Transfer list to array because that's what the table model constructor expect...
ConcoursTestModel.TableColHeader[] headerArray = new ConcoursTestModel.TableColHeader[headerList.size()];
headerList.toArray(headerArray); // fill the headerArray
//
// The schedule table RowData must also be extracted from theConcoursModel
//
Object [][] rowArray = theConcoursModel.UpdateScheduleTableRowData(headerList);
// Now construct the Table Model
scheduletable.setModel(new javax.swing.table.DefaultTableModel(
rowArray,
headerArray
));
schedulescrollpane.setViewportView(scheduletable);
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)
.addGroup(layout.createSequentialGroup()
.addContainerGap())
.addComponent(schedulescrollpane)))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(24, 24, 24)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(schedulescrollpane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
JTableHeader tableHeader = scheduletable.getTableHeader();
tableHeader.setBackground(java.awt.Color.lightGray);
Dimension d = super.getPreferredSize();
d.height = HEADER_HEIGHT; // this doesn't work!
// Adjust the column widths to fit the data
scheduletable.setRowHeight(ROW_HEIGHT);
int width;
for(int j = 0; j < scheduletable.getColumnCount(); j++){
// Calculate best column width
width = 0;
for (int row = 0; row < scheduletable.getRowCount(); row++) {
TableCellRenderer renderer = scheduletable.getCellRenderer(row, j);
Component comp = scheduletable.prepareRenderer(renderer, row, j);
width = Math.max (comp.getPreferredSize().width, width);
}
TableColumn c = scheduletable.getColumnModel().getColumn(j);
c.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(ConcoursTestGUIDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(ConcoursTestGUIDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(ConcoursTestGUIDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(ConcoursTestGUIDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the dialog */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
ConcoursTestGUIDialog dialog = new ConcoursTestGUIDialog(new javax.swing.JFrame(), true);
dialog.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent e) {
System.exit(0);
}
});
dialog.setVisible(true);
}
});
}