Previous | Next | Trail Map | To 1.1 -- And Beyond! | GUI Changes: The AWT Grows Up

How to Use Tables

With the JTable(in the API reference documentation) class, you can display tables of data. JTable doesn't contain or cache data; it's simply a view of your data. This lack of caching makes JTable perform well, even when its data comes from a huge database. JTable has too many features to be completely described in this tutorial, so we'll cover the features we expect most programmers to use. [X-Ref to other doc]

To use JTable, you must write a data model -- the object that supplies data to the table. You can do this by making a subclass of the JTableDataModelAdapter(in the API reference documentation) class. A table data model contains methods for getting and setting data values, getting the number of rows (records) of data, and adding and removing table listeners. (Table listeners are objects such as the JTable that are notified each time the data model changes.)

When you initialize a JTable, you must provide a JTableColumn(in the API reference documentation) object for each column. Each JTableColumn object identifies a column of data and specifies how it should be displayed.

Here is a picture of an application that displays a table in a scroll pane:

Try this:
  1. Compile and run the application. The source file is
    See Getting Started with Swing if you need help.
  2. Click a cell.
    The entire row is selected. This is intended to remind you that JTable implements a database browser, not a spreadsheet.
  3. Position the cursor over the "First Name" heading. Now press the mouse button and drag the heading to the right.
    As you can see, users can rearrange columns in tables. This flexible positioning is why columns are specified by objects (such as strings), instead of indexes (such as are used for rows).
  4. Position the cursor just to the right of a heading. Now press the mouse button and drag to the right or left.
    The column changes size.
  5. Resize the window containing the table so that it's bigger than necessary to display the whole table.
    The table cells stay the same size, and they're clustered at the upper left of the display area.

Below is the code from that implements the table in the previous example.

//In initialization code in a JPanel subclass:
	MyDataModel myDataModel = new MyDataModel();
	JTable table = new JTable(myDataModel);

	for (int columnIndex = 0; 
	         columnIndex < myDataModel.numColumns;
	         columnIndex++) {
	    JTableColumn newColumn = new JTableColumn(

        //Create the scroll pane and add the table to it. 
	JScrollPane scrollPane = new JScrollPane();

	//Make the table heads be the non-scrolling column header.
	JViewport columnHeading = new JViewport();
	columnHeading.setLayout(new BoxLayout(columnHeading, 	//HACK
. . .
class MyDataModel extends JTableDataModelAdapter {
    //Dummy data.
    final Object[][] data = {
	{"First Name", "Mary", "Alison", "Kathy", "Mark", "Angela"},
	{"Last Name", "Campione", "Huml", "Walrath", "Andrews", "Lih"},
	{"Sport", "Snowboarding", "Rowing", "Chasing toddlers", "Speed reading", "Teaching high school"},
	{"Est. Years Experience", "5", "3", "2", "20", "4"},

    public int numColumns = data.length;
    protected int numRows = data[0].length - 1;

    public int getRowCount() {
	return numRows;

    public Object getValueAt(Object columnIdentifier, int rowIndex) {
	for (int columnIndex = 0; columnIndex < numColumns; columnIndex++) {
	    if (data[columnIndex][0].equals(columnIdentifier)) {
		return data[columnIndex][rowIndex+1];
	return "NO DATA";

    public void setValueAt(Object aValue,
			   Object columnIdentifier,
			   int rowIndex) {

    /** This method isn't in TableDataModel.  */
    public String getColumnName(int columnIndex) {
	return (String)data[columnIndex][0];
[Now show an editable tree.]

Previous | Next | Trail Map | To 1.1 -- And Beyond! | GUI Changes: The AWT Grows Up