Column Class and Display
A table's data lives in a table model, and methods such as setValueAt, removeRow, and addRow change that data; the view updates automatically.
A Table Edit Starts Somewhere Other Than the Table
Suppose a program shows a grid of student names and scores, and a user types a new score into one cell. Where does that new score go, and who is responsible for redrawing the grid? Many beginners expect to find code that edits the visible table. The source material for this topic shows that the answer is different: the table does not own the data it displays.
What do you think happens?
If a column is declared to hold Boolean values, how do you expect its cells to look and behave?
Reveal answer
As check boxes that can be ticked and unticked
The source states that a column specified to hold Boolean values is displayed and edited as check boxes. The mechanism that makes this happen is the column class, which the rest of this article traces step by step.
Where the Data Actually Lives
A JTable is the visible component. It does not own the data it displays. The data lives in a table model, and DefaultTableModel is the standard model that provides methods for changing it. Think of the model as the single store of truth and the JTable as a view that reads from that store.
Three DefaultTableModel methods do most of the work. setValueAt takes an item along with a row number and a column number, and it replaces the item in that one cell. removeRow takes a row number and deletes that row. addRow takes an array of items and appends a new row at the end of the table, filling its cells with those items.
Following an Edit from Model to Screen
The important point is where you make the change. You call setValueAt, addRow, or removeRow on the model, never on the visible table. The source states that when the model is modified, the view is automatically updated to reflect the change. You do not write separate code to redraw the table after an edit. The model is the one place where data changes, and the view follows it.
Clearing a Cell Versus Deleting a Row
Setting a cell to null is a special case. The source says that if the item in a given cell is set to null, that cell becomes empty. Empty is not the same as deleted: the row still exists, and only the value in that one cell is cleared. Removing a row with removeRow takes the whole row out of the table. The short trace below uses a model that already has two columns named Name and Score, and it follows each change through the model.
model.addRow(new Object[]{"Ann", 90});
model.addRow(new Object[]{"Ben", 75});
model.setValueAt(82, 1, 1);
model.setValueAt(null, 0, 1);
model.removeRow(0);- 1Line 1 adds a row whose cells hold Ann and 90. The row is placed at the end of the model.
- 2Line 2 adds a second row for Ben and 75 beneath Ann.
- 3Line 3 changes only one cell: row 1, column 1, which is Ben's score. Ben's name is untouched.
- 4Line 4 sets Ann's score cell to null. The cell is empty, and Ann still occupies row 0.
- 5Line 5 removes the entire row at index 0. Ann and her empty score both disappear from the table.
addRowappends Ann to the end of the table at row 0addRowappends Ben below Ann at row 1setValueAtreplaces the item in row 1, column 1, so Ben's score becomes 82setValueAtwith null leaves Ann's score cell empty; Ann's row still existsremoveRow(0)deletes Ann's entire row, not just her score
Row Positions After a Removal
When you remove a row from the middle of the model, the rows below it do not keep their old positions. The source describes removeRow as deleting a row, and it describes the model as the source of what the view shows. A consequence follows from that: each row below the deleted one moves up by one index, so the view's row position for a given item is always the model's current row position. This is a reasoning step drawn from the described behavior, not a separate rule the source spells out.
How getColumnClass Chooses Display and Editing
The table does not guess what kind of data a column holds by looking at its cells. For each column, it calls getColumnClass and uses the class that the method returns to decide how to display and edit that column's items. The decision therefore depends entirely on what the method returns for that column number. If you want to know why a column looks or behaves a certain way, the return value of getColumnClass for that column is the place to look.
The source gives two documented consequences of the returned class. First, a column specified to hold Boolean values has its cells displayed and edited as check boxes. Second, for numeric types the table will not accept illegal input when the user types a value. The source presents these two as examples and does not list every class and its appearance, so treat these two as the documented cases.
What do you think happens?
A column's getColumnClass returns a numeric class. A user types letters into one of its cells. What does the table do?
Reveal answer
It refuses the illegal input
The source states that for numeric types the table will not accept illegal input when the user types a value. The check happens because of the class that getColumnClass returned for that column.
Customizing Editors and Renderers
Mistakes Learners Make with Table Edits
Common mistake Trying to change what the table shows by editing the JTable itself
Why it failsThe source states that the data lives in the table model and that the view updates automatically when the model changes.
Do this insteadCall setValueAt, addRow, or removeRow on the DefaultTableModel and let the view follow.
Common mistake Assuming setting a cell to null deletes the row
What it looks likesetValueAt(null, 0, 1) leaves row 0 in place with an empty cell.
Why it failsThe source says a null cell is empty, and the row still exists. Only
removeRowtakes a whole row out.Do this insteadUse removeRow(row) when the entire row should disappear.
Common mistake Expecting the table to infer a column's type from the values in its cells
Why it failsThe source says the table calls
getColumnClassfor each column and uses the returned class, not the cell contents.Do this insteadCheck what getColumnClass returns for that column number.
Common mistake Assuming row numbers stay fixed after a deletion
What it looks likeAfter removeRow(1) on a four-row model, the item formerly at row 2 is at row 1.
Why it failsRemoving a row takes it out of the model, so the remaining rows below it are at new positions.
Do this insteadRead row positions from the model's current state rather than from earlier notes.
Diagnosing a Wrong Table Result
When a table behaves differently from what you expected, work through three checks in the order below. This order follows the path the data takes, so each check either locates the problem or rules out a layer.
- 1Check the model: did the
setValueAt,removeRow, oraddRowcall change the data you thought it changed? - 2Check the column class: what does
getColumnClassreturn for the column that misbehaves? - 3Check customization: has the
JTable's default editor or renderer been changed throughsetDefaultEditororsetDefaultRenderer?
A table's Score column shows a check box in every row, but you expected a number. Using the three checks in order, describe what you would verify first and what each check would rule in or out.
Hints
- Start with the model. Is the stored value in the Score column what you intended?
- Next, look at what
getColumnClassreturns for the Score column number. - Only after the first two checks should you consider whether a default renderer or editor was customized.
Key Takeaways
- A
JTabledoes not own its data; aDefaultTableModelholds it, and you change the table by callingsetValueAt,removeRow, oraddRowon the model, after which the view updates automatically. setValueAtreplaces one cell, setting a cell to null leaves it empty,removeRowdeletes a whole row, andaddRowappends a new row at the end.- The table calls
getColumnClassfor each column and uses the returned class to decide display and editing; Boolean columns become check boxes, and numeric columns refuse illegal input. - When results diverge, check the model first, then the column class returned by
getColumnClass, then whethersetDefaultEditororsetDefaultRendererhas been customized.