Modifying Table Models
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 Guess Before the Edit
A table on screen looks like the thing that holds your data, but it is only the part that draws the data. When a program needs to change what the user sees, it changes the data behind the table, and the table redraws itself to match. This article follows that path step by step, so that when a table shows something unexpected you know exactly where to look.
What do you think happens?
A DefaultTableModel has 4 rows. You call setValueAt(null, 2, 1). How many rows does the table have afterward?
Reveal answer
4
Setting a cell to null only empties that one cell. The source says the cell becomes empty, and empty is different from deleted. The row still exists, so the table still has 4 rows. Only removeRow takes a whole row out.
Where the Data Lives
A JTable 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. The table is the view: it reads from the model and draws what it finds there. Because of this split, the place where you make a change matters more than the code that draws the change.
You call the change methods on the model, not on the visible table. The source states that when you modify the model, the view is automatically updated to reflect the changes. You never write separate code to redraw the table after an edit. The model is the single place where data changes, and the view follows it.
Edit the model, never the drawn table. The table displays whatever the model currently holds, so a correct edit to the model is the only edit you need.
Three Methods That Change the Model
Three methods on DefaultTableModel do most of the work. Each one changes the stored data in a specific way, and each has a different effect on the number of rows. The subsections below take them one at a time.
Tracing a Small Table Edit
The following small program builds a model with two columns, adds two rows, changes one cell, and then removes the first row. The code is an original teaching example written to use the three methods described in the source. Read it once, then follow it with the worked example below.
DefaultTableModel model = new DefaultTableModel(new Object[]{"Name", "Score"}, 0);
model.addRow(new Object[]{"Ana", 90});
model.addRow(new Object[]{"Ben", 75});
model.setValueAt(82, 1, 1);
model.removeRow(0);- 1Line 1 creates the model that holds the data. The table that displays it would be attached to this model.
- 2Line 2 appends a row at the end of the table. Ana is now at row index 0.
- 3Line 3 appends Ben at row index 1.
- 4Line 4 changes only one cell, the score in row 1. No row is added or removed.
- 5Line 5 deletes the whole row at index 0. Ben, who was at index 1, moves up to index 0 because the rows below a removed row shift up.
- Creates a model with two columns and zero rows to start
addRowappends Ana at index 0addRowappends Ben at index 1setValueAtreplaces the score in row 1, column 1 onlyremoveRowdeletes row 0, which is Ana; Ben moves up to index 0
Tracking a Four-Row Table Through Three Edits
The model starts with four rows: Ana, Ben, Cara, and Dev in column 0, with scores in column 1. Apply these changes in order: clear Cara's score with setValueAt(null, 2, 1), remove row 1 with removeRow(1), then append Eli with score 88 using addRow. What does the table hold at the end?
- 1Start state
Four rows exist at indexes 0 to 3: Ana at 0, Ben at 1, Cara at 2, Dev at 3.
- 2setValueAt(null, 2, 1)
Only Cara's score cell is replaced with null, so it becomes empty. Cara's row still exists, and the table still has four rows.
- 3removeRow(1)
Row 1 is Ben, so Ben's whole row is deleted. Cara and Dev each move up one index: Cara is now at 1 and Dev is now at 2. The table has three rows.
- 4addRow with Eli and 88
The new row is appended after the last existing row, so Eli takes index 3. Existing rows do not move.
Four rows: Ana at 0, Cara at 1 with an empty score, Dev at 2, and Eli at 3 with score 88. Ben is gone.
Why Row Indexes Shift After removeRow
After removeRow deletes a row, the rows below it take up the vacated positions. The row numbers you used before the deletion no longer refer to the same data. In the worked example, Cara was at index 2 before Ben was removed, and at index 1 afterward. Any code that stored the number 2 and reused it after the removal would now be reading Dev's row, not Cara's. This is why a stale index can point to the wrong data even though nothing in the code looks wrong.
How getColumnClass Chooses Cell Behavior
The table does not guess what kind of data a column holds by looking at the values in 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 depends entirely on what the method returns for that column number, which is why the return value is worth tracing.
The source gives two documented consequences of the returned class. First, if a column is specified to hold Boolean values, its cells are 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 does not list every possible class and its appearance, so this article treats these two as the documented cases.
Changing the data does not change the column class. If a column's cells look wrong, first confirm what getColumnClass returns for that column, because that return value is what the table uses to choose its display and editing behavior.
Mistakes When Changing Table Models
Common mistake Using null when the row should disappear
What it looks likemodel.setValueAt(null, 1, 0) expecting Ben's row to vanishWhy it failsSetting a cell to null only empties that cell. The source says the row still exists.
Do this insteadUse model.removeRow(1) to delete the whole row.
Common mistake Writing separate code to redraw the table after each edit
Why it failsThe source states that the view is automatically updated when the model changes, so extra redraw code is not needed to show the change.
Do this insteadMake the change on the model and let the table follow it.
Common mistake Reusing a row index after removing a row above it
What it looks likeStoring Cara's index as 2, calling removeRow(1), then calling setValueAt on row 2
Why it failsAfter
removeRow(1), Cara moved to index 1 and Dev is at index 2, so row 2 now refers to Dev.Do this insteadLook up the row again after a removal, or update any stored index when rows move.
Common mistake Assuming the column class is inferred from the values
Why it failsThe source says the table calls
getColumnClassand uses its return value. It does not inspect the cells to decide.Do this insteadCheck what getColumnClass returns for that column number.
Tracing a Misbehaving Cell
When a table displays or edits incorrectly, the source recommends three checks in a fixed order. This order follows the path the data takes, so you can find the point where the result diverged from what you expected.
- 1Check the model first: did the
setValueAt,removeRow, oraddRowcall change the data you thought it changed? Confirm the row and column numbers, because a wrong index writes to the wrong cell. - 2Check the column class next: what does
getColumnClassreturn for the column that misbehaves? A Boolean return gives check boxes, and a numeric return refuses illegal typed input. - 3Check JTable customization last: has the table's default editor or renderer been changed? The source points to the
JTablemethodssetDefaultEditorandsetDefaultRendererfor this, and it names them without showing their full signatures, so consult the Java documentation for their exact use.
Practice: Predicting the Table State
A model has three rows: Ana, Ben, and Cara. Predict the table after these calls, in order: model.removeRow(0); then model.setValueAt(null, 1, 1); then model.addRow(new Object[]{"Dev", 60}). Write down the row count and the row at each index before you check your answer against the worked example above.
Hints
removeRowdeletes the whole row, and the rows below it move up by one index.- After
removeRow(0), the rows are Ben at 0 and Cara at 1, so the next call targets row 1 which is Cara. addRowalways appends at the end, so Dev takes the next free index.
Key Takeaways
- A
JTabledisplays data from a table model. You change what the user sees by callingsetValueAt,addRow, orremoveRowon the model, and the view updates automatically. setValueAtreplaces one cell and keeps the row count. Passing null empties that cell but keeps the row.removeRowdeletes a whole row, and the rows below it shift up.addRowappends a new row at the end.- The table calls
getColumnClassfor each column and uses the returned class to decide how items are displayed and edited. A Boolean class gives check boxes, and numeric classes refuse illegal input. - When a cell misbehaves, check the model first, then the column class, then whether
JTable's default editor or renderer has been customized.