JTable : Java Glossary

The JDisplay Java Applet displays the large program listings on this web page. JDisplay requires an up-to-date browser and Java version 1.8+, preferably 1.8.0_131. If you can’t see the listings, or if you just want to learn more about JDisplay, click  Help Use Firefox for best results.

Swing’s component for displaying tables, much like a spreadsheet.
JTable Classes TableCellRenderer Gotchas
Limitations TableRowSorter
How JTables Work Simple Example
Wide JTables Real World Example
Useful Classes Learning More
Strategy Links


The most common bugs in using JTables are: JTables are tricky. I strongly suggest buying a textbook that covers them rather than trying to figure it out all on your own from the Javadoc.

Classes to implement a JTable

You actually need a family of components:


JTables are not as flexible as HTML (Hypertext Markup Language) tables. Cells cannot span multiple rows or multiple columns. It is possible to change the height of a row from the default 16 pixels with JTable. setRowHeight or width of column with TableColumn. setWidth. In addition you can arrange that the user can change the column widths with dragging.

JTabless are tricky. It is not that anything is that difficult, it is just that there are so many classes and so many methods to master. JTables are more like the plans for a do-it-yourself table than a table-creating appliance. I strongly suggest buying a textbook that covers them rather than trying to figure it out all on your own from the Javadoc.

How JTables Work

The key thing to understand is the data live only in the DataModel. The only rendered data are what is currently visible. There is no giant bit map scrolling off screen. There is no corresponding giant grid of JComponents. There is not even a single row of JComponents. A TableCellRenderer renders all its cells recycling the same JComponent. Whenever the user scrolls, new rows are fetched from the DataModel and rendered. The bit map for the rendered rows still visible is slid down in a rapid bit/blt move. This scheme allows rapid scrolling over a DataModel that might not even be totally RAM-resident.

Wide JTables

If your JTables are too wide what can you do?

Useful Classes and Interfaces

Classes and Interfaces Useful in Creating JTables
Class Use
AbstractTableModel implements the TableModel with your own class to represent each row.
DefaultCellEditor Implements TableCellEditor for some common data types.
DefaultTableCellRenderer Implements TableCellRenderer for some common data types, including ImageIcon.
DefaultTableModel implements the TableModel with each row represented by a Vector.
JTable Represents the entire table.
JTableHeader Represents all the header columns.
ListSelectionModel Methods to track which rows are selected.
TableCellEditor Methods to edit a single cell.
TableCellRenderer Methods to display a single cell, both data and headers.
TableColumn Represents one column, widths etc. Used to attach TableCellRenderers for both data and headers.
TableColumnModel information about all columns.
TableModel Represents the data in the table grid.
TableModelEvent notify listeners that a table model has changed
TableRowSorter Keep rows sorted.Java version 1.6 or later only.


JTables can be overwhelming. It is hard to plan everything out before you start. So here is a muddle through approach. You add a little bit, then compile. If you don’t understand everything just compose dummy methods you can come back to later.
  1. Define your JTable and a ScrollPane to contain it.
  2. Use the JTable constructor that takes only one parameter, the TableModel.
  3. Define your custom TableModel class, perhaps making it an inner class. Have it extend AbstractTableModel or DefaultTableModel. Use AbstractTableModel if your rows are represented by a proper class and DefaultTableModel if they are represented by a Vector of fields. Don’t try to compose your model totally from scratch by implementing every method in TableModel.
  4. Use your IDE (Integrated Development Environment) to provide skeletons for the methods you absolutely must override.
  5. Look over the methods in your base class to see which ones need overriding and write the code.
  6. Declare a RowOfCells class whose elements are the data for one row. Pick a more descriptive name than that, please. Write getters and setters for the fields.
  7. Declare an ArrayListRowOfCells allRows to hold all the data for the table.
  8. Define a set of constants to name each of the columns defining the 0-based column number.
  9. Write add, set, remove etc. methods to let you change the rows in the model. Base them on the corresponding ArrayList methods. Make sure you call fireTableRowsInserted, fireTableRowsUpdated or fireTableRowsDeleted to notify Swing of the changes you made to the underlying data.
  10. Write your Object getValueAt( int rowIndex, int columnIndex ). Don’t change the Object to something else, or you won’t override the correct method. It will need a switch to use a different getter depending on the column.
  11. Write your setValueAt( Object aValue, int rowIndex, int columnIndex ). Don’t change the Object to something else, or you won’t override the correct method. You can leave this out or use a dummy if your table is not editable.
  12. Test your data-model modifying methods by using them to put some dummy data into the table, rather than trying to handle keyboard input just yet. It may be easier to add one column at a time to your model and get that column completely working with custom renderers and editors. They you can clone that working, debugged code for the other columns, rather than your first cut buggy code.
  13. Hookup buttons or menu items to call the add and remove row methods.
  14. Set your column width with  JTable.getColumnModel and setPreferredWidth.
  15. Write a TableCellRenderer to chose the fonts and colours of your heading. Install with TableColumn. setHeaderRenderer.
  16. Add your persistence mechanism to load up allRows and save on exit. Make sure suitable event changes get fired. You might save to disk, to the registry via the Preferences mechanism or to a server.
  17. Compose your custom TableCellRenderers for the data in each column. Hook them up with TableColumn. setCellRenderer.
  18. Add sorts to your TableModel, remembering to fireTableDataChanged. You can trigger them with TableHeader. addMouseListener. In Java version 1.6 or later JTables have built-in javax.swing.table. TableRowSorters.
  19. Add your editing and custom TableCellEditors. It can be as simple as:
    // attaching a TableCellEditor to a column
    tableColumn.setCellEditor( new DefaultCellEditor( comboBox ) );
    where comboBox is a JComboBox scratch component the user is allowed to edit. DefaultCellEditor will handle popping up the scratch edit component, initialising it and sending the new value to the TableModel. To do more elaborate edits, search for sample code on the web. If you apply colours and fonts to your scratch components, it will make it clearer to the user which cell he is editing. The crucial methods are:
    • getTableCellEditorComponent which converts an Object value taken from from the TableModel via getValueAt to a displayable GUI object, e.g. a JTextField.
    • getCellEditorValue which extracts a String from the GUI component and converts it to an Object suitable for storing in the TableModel via setValueAt. You can just throw an Exception if you don’t like the value, perhaps make a noise too. The value will revert to the previous if the user does not fix the problem.
  20. Add calls to stopEdit just prior to any time you sort, insert, delete or replace rows. JTable does not do this by default. Without this code, a field being edited will be improperly left where it was, ending up on the wrong line.
  21. Insert code to make sure a given row is visible in your scroll region like this:
  22. Add threads so that the computation is on its own thread with the Swing thread free to keep the GUI up to date. Add synchronized to TableModel methods as needed. Make sure the model is not locked when you call the various fire methods because those events will need to get at the model via getValueAt to repaint the GUI. Pepper your code with Thread.yield () after you call methods that could change the GUI. This will give the Swing thread a bash at processing the generated GUI-changing events. Remember that all the JTable methods including fireTableCellUpdated and brethren must be invoked only from the Swing thread. This means the calls must often be wrapped in SwingUtilities. invokeLater. Normally you need to make your TableModel thread-safe because JTable will call its methods on the Swing thread to discover the data values and your app will call its methods on some other thread to set the data values.
  23. Hook up Listeners to the ListSelectionModel if there is anything you want to when the selection changes. ListSelectionEvent. getFirstIndex and ListSelectionEvent. getLastIndex do not give you the bounds of selected rows. They give you the range of rows whose selection status may have changed.
  24. Review the methods of JTable, ListSelectionModel, DefaultTableModel and DefaultTableCellRenderer reading the documentation and looking for methods to tweak the implementation. When you are looking for a method, scan all those classes. Often the method you are looking for is not where you expect and is not called what you might expect. Using a text search tool on the Javadoc can be a great help to find what you are looking for as can examining the source code.

TableCellRenderer Gotchas


TZ: a Simple Example

Here is a simple example using a JTable that uses a TableRowSorter to let the user sort by any of the columns. It displays a list of all the time zones that view

VerCheck: a Real World Example

Here is a real world example of a signed Applet that uses a JTable. browse vercheck source in repository.

Learning More

To see some simple sample code implementing a JTable, see the source code for the TimeZones Applet.
Oracle’s Javadoc on JTable class : available:
Oracle’s Javadoc on TableModel interface : available:
Oracle’s Javadoc on AbstractTableModel class : available:
Oracle’s Javadoc on DefaultTableModel class : available:
Oracle’s Javadoc on TableModelEvent class : available:
Oracle’s Javadoc on TableColumnModel interface : available:
Oracle’s Javadoc on TableColumn class : available:
Oracle’s Javadoc on TableCellRenderer interface : available:
Oracle’s Javadoc on DefaultTableCellRenderer class : available:
Oracle’s Javadoc on JTableHeader class : available:
Oracle’s Javadoc on TableCellEditor interface : available:
Oracle’s Javadoc on DefaultCellEditor class : available:
Oracle’s Javadoc on ListSelectionModel interface : available:
Oracle’s Javadoc on TableRowSorter class : available:

This page is posted
on the web at:


Optional Replicator mirror
of mindprod.com
on local hard disk J:

Canadian Mind Products
Please the feedback from other visitors, or your own feedback about the site.
Contact Roedy. Please feel free to link to this page without explicit permission.

Your face IP:[]
You are visitor number