The JavaTM Tutorial

| Start of Tutorial > Start of Trail > Start of Lesson | Search Feedback Form

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components

## How to Use Tables

> With the `JTable` class you can display tables of data, optionally allowing the user to edit the data. `JTable` doesn't contain or cache data; it's simply a view of your data. Here's a picture of a typical table displayed within a scroll pane:

> The rest of this section tells you how to accomplish some common table-related tasks. Here are the topics this section covers:
> - Creating a Simple Table
> - Adding a Table to a Container
> - Setting and Changing Column Widths
> - Detecting User Selections
> - Creating a Table Model
> - Detecting Data Changes
> - Concepts: Cell Editors and Renderers
> - Validating User-Entered Text
> - Using a Combo Box as an Editor
> - Specifying Other Editors
> - Further Customizing Table Display and Event Handling
> - Sorting and Otherwise Manipulating Data
> - The Table API
> - Examples that Use Tables

### Creating a Simple Table

> > Try this:
> > 1. Compile and run `SimpleTableDemo`. The source file is `SimpleTableDemo.java`.
> >    See Getting Started with Swing if you need help compiling or running this application.
> > 2. Click the cell that contains "Snowboarding".
> >    The entire first row is selected, indicating that you have selected Mary Campione's data. A special highlight indicates that the "Snowboarding" cell is editable. Generally, you begin editing a text cell by double-clicking it.
> > 3. Position the cursor over "First Name". Now press the mouse button and drag to the right.
> >    As you can see, users can rearrange columns in tables.
> > 4. Position the cursor just to the right of a column header. Now press the mouse button and drag to the right or left.
> >    The column changes size, and the other columns adjust to fill the remaining space.
> > 5. Resize the window containing the table so that it's bigger than necessary to display the whole table.
> >    All the table cells become larger, expanding to fill the extra space.

> Here is the code that implements the table in `SimpleTableDemo.java`:

> >     Object[][] data = {
> >         {"Mary", "Campione",
> >          "Snowboarding", new Integer(5), new Boolean(false)},
> >         {"Alison", "Huml",
> >          "Rowing", new Integer(3), new Boolean(true)},
> >         {"Kathy", "Walrath",
> >          "Chasing toddlers", new Integer(2), new Boolean(false)},
> >         {"Mark", "Andrews",
> >          "Speed reading", new Integer(20), new Boolean(true)},
> >         {"Angela", "Lih",
> >          "Teaching high school", new Integer(4), new Boolean(false)}
> >     };

> >     String[] columnNames = {"First Name",
> >                             "Last Name",
> >                             "Sport",
> >                             "# of Years",
> >                             "Vegetarian"};

> >     final JTable table = new JTable(data, columnNames);

> The `SimpleTableDemo` example uses one of two `JTable` constructors that directly accept data:
> - `JTable(Object[][] rowData, Object[] columnNames)`
> - `JTable(Vector rowData, Vector columnNames)`
> The advantage of these constructors is that they're easy to use. However, these constructors also have disadvantages:
> - They automatically make every cell editable.
> - They treat all data types the same. For example, if a table column has `Boolean` data, the table can display the data in a check box. However, if you use one of the two `JTable` constructors listed previously, your `Boolean` data will be displayed as a string. You can see this difference in the last column of the two previous pictures of tables.
> - They require that you put all of the table's data in an array or vector, which isn't appropriate for some data. For example, if you're instantiating a set of objects from a database, you might want to query the objects directly for their values, rather than copying all their values into an array or vector.
> If you want to get around these restrictions, you need to implement your own table model, as described in Creating a Table Model.

### Adding a Table to a Container

> It's easy to put a table in a scroll pane. You need just one or two lines of code:

> >     JScrollPane scrollPane = new JScrollPane(table);
> >     table.setPreferredScrollableViewportSize(new Dimension(500, 70));

> The scroll pane automatically gets the table's header, which displays the column names, and puts it on top of the table. Even when the user scrolls down, the column names remain visible at the top of the viewing area. The scroll table also tries to make its viewing area the same as the table's preferred viewing size. The previous code snippet sets the table's preferred viewing size with the `setPreferredScrollableViewportSize` method.

> > Note: Before Swing 1.0.2, the scroll pane didn't get the table header unless you created the scroll pane using the `JTable.createScrollPaneForTable` method. Here are examples of the recommended code, before and after Swing 1.0.2:

> >     //1.0.1 code (causes deprecation warning
> >     //in 1.0.2 and later releases):
> >     scrollPane = JTable.createScrollPaneForTable(table);

> >     //Recommended code (causes missing column names in 1.0.1):
> >     scrollPane = new JScrollPane(table);

> If you're using a table without a scroll pane, then you must get the table header component and place it yourself. For example:

> >     container.setLayout(new BorderLayout());
> >     container.add(table.getTableHeader(), BorderLayout.NORTH);
> >     container.add(table, BorderLayout.CENTER);

### Setting and Changing Column Widths

> By default, all columns in a table start out with equal width, and the columns automatically fill the entire width of the table. When the table becomes wider or narrower (which might happen when the user resizes the window containing the table), all the column widths change appropriately.

> When the user resizes a column by dragging its right border, then either other columns must change size, or the table's size must change. By default, the table's size remains the same, and all columns to the right of the drag point resize to accommodate space added or removed from the column to the left of the drag point.

> The following figures illustrate the default resizing behavior.

> Initially, the columns have equal width.

> When the user resizes a column, some of the other columns must adjust size for the table to stay the same size.

> When the entire table is resized, all the columns are resized.

> To customize initial column widths, you can invoke `setPreferredWidth` on each of your table's columns. This sets both the preferred widths of the columns and their approximate relative widths. For example, adding the following code to `SimpleTableDemo` makes its third column bigger than the other columns:

> >     TableColumn column = null;
> >     for (int i = 0; i < 5; i++) {
> >         column = table.getColumnModel().getColumn(i);
> >         if (i == 2) {
> >             column.setPreferredWidth(100); //sport column is bigger
> >         } else {
> >             column.setPreferredWidth(50);
> >         }
> >     }

> > Note: The `setPreferredWidth` method was first introduced in Swing 1.1 Beta 2. For previous releases, you must use `setMinWidth` instead, making sure to invoke it on every column. (Otherwise, the columns you miss will be very thin.)

> As the preceding code shows, each column in a table is represented by a `TableColumn` object. Besides `setPreferredWidth`, `TableColumn` also supplies methods for getting and setting the minimum, current, and maximum width of a column. For an example of setting cell widths based on the actual amount of space needed to draw the cells' contents, see the `initColumnSizes` method in `TableRenderDemo.java`, which is discussed in Further Customizing Table Display and Event Handling.

> When the user explicitly resizes columns, the new sizes become not only the columns' new current widths, but also the columns' new preferred widths, However, when columns are resized as the result of the table width changing, the columns' preferred widths do not change.

> You can change a table's resize behavior by invoking the `setAutoResizeMode` method. The method's argument should have one of these values (defined as constants in `JTable`):

> `AUTO_RESIZE_SUBSEQUENT_COLUMNS`
>   The default. In addition to resizing the column to the left of the drag point, adjusts the sizes of all columns to the right of the drag point.
> `AUTO_RESIZE_NEXT_COLUMN`
>   Adjusts only the columns immediately to the left and right of the drag point.
> `AUTO_RESIZE_OFF`
>   Adjust the table size instead.

>   > Note: Before the Swing 1.1 Beta release, the default resize mode was `AUTO_RESIZE_ALL_COLUMNS`. However, that mode isn't intuitive, so we changed the default mode to a mode added in Swing 1.1 Beta: `AUTO_RESIZE_SUBSEQUENT_COLUMNS`.

### Detecting User Selections

> The following code snippet shows how to detect when the user selects a table row. By default, a table allows the user to select multiple rows -- not columns or individual cells -- and the selected rows need not be next to each other. Using the `setSelectionMode` method, the following code specifies that only one row at a time can be selected. You can find the entire program in `SimpleTableSelectionDemo.java`.

> >     table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
> >     ...
> >     ListSelectionModel rowSM = table.getSelectionModel();
> >     rowSM.addListSelectionListener(new ListSelectionListener() {
> >         public void valueChanged(ListSelectionEvent e) {
> >             //Ignore extra messages.
> >             if (e.getValueIsAdjusting()) return;

> >             ListSelectionModel lsm =
> >                 (ListSelectionModel)e.getSource();
> >             if (lsm.isSelectionEmpty()) {
> >                 ...//no rows are selected
> >             } else {
> >                 int selectedRow = lsm.getMinSelectionIndex();
> >                 ...//selectedRow is selected
> >             }
> >         }
> >     });

> `SimpleTableSelectionDemo.java` also has code (not included in the preceding snippet) that changes the table's selection orientation. By changing a couple of boolean values, you can make the table allow either column selections or individual cell selections, instead of row selections.

> For more information and examples of implementing selection, see How to Write a List Selection Listener.

### Creating a Table Model

> As the following figure shows, every table gets its data from an object that implements the `TableModel` interface.

> The `JTable` constructor used by `SimpleTableDemo` creates its table model with code like this:

> >     new AbstractTableModel() {
> >         public String getColumnName(int col) {
> >             return columnNames[col].toString();
> >         }
> >         public int getRowCount() { return rowData.length; }
> >         public int getColumnCount() { return columnNames.length; }
> >         public Object getValueAt(int row, int col) {
> >             return rowData[row][col];
> >         }
> >         public boolean isCellEditable(int row, int col)
> >             { return true; }
> >         public void setValueAt(Object value, int row, int col) {
> >             rowData[row][col] = value;
> >     	fireTableCellUpdated(row, col);
> >         }
> >     }

> As the preceding code shows, implementing a table model can be simple. Generally, you implement your table model in a subclass of the `AbstractTableModel` class.

> Your model might hold its data in an array, vector, or hashtable, or it might get the data from an outside source such as a database. It might even generate the data at execution time. For examples of getting data from a database, see the table examples provided as part of the JFC/Swing and Java 2 Standard Edition SDK releases. In JFC/Swing-only releases (for use with JDK 1.1) the table examples are in the `examples/Table` directory. In J2SE v 1.2, the table examples are in `demo/jfc/Table` directory. In J2SE v 1.3, the examples move to the `demo/jfc/TableExamples` directory.

> Here again is a picture of a table implemented by `TableDemo`, which has a custom table model:

> This table is different from the `SimpleTableDemo` table in the following ways:
> - `SimpleTableDemo`'s table model, having been created automatically by `JTable`, isn't smart enough to know that the # of Years column contains numbers (which should generally be right aligned). It also doesn't know that the `Vegetarian` column contains boolean values, which can be represented by check boxes. `TableDemo`'s custom table model, even though it's simple, can easily determine the data's type, helping the `JTable` display the data in the best format.
> - In `SimpleTableDemo`, all cells are editable. In `TableDemo`, we implemented the custom table model so that it doesn't let you edit the name columns; it does, however, let you edit the other columns.

> Below is the code from `TableDemo.java` that is different from the code in `SimpleTableDemo.java`. Bold font indicates the code that makes this table's model different from the table model defined automatically in `SimpleTableDemo`.

> >     public TableDemo() {
> >         ...
> >         MyTableModel myModel = new MyTableModel();
> >         JTable table = new JTable(myModel);
> >         table.setPreferredScrollableViewportSize(
> >                   new Dimension(500, 70));

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

> >         //Add the scroll pane to this window.
> >         setContentPane(scrollPane);
> >         ...
> >     }

> >     class MyTableModel extends AbstractTableModel {
> >         final String[] columnNames = ...//same as before...
> >         final Object[][] data = ...//same as before...

> >         public int getColumnCount() {
> >             return columnNames.length;
> >         }

> >         public int getRowCount() {
> >             return data.length;
> >         }

> >         public String getColumnName(int col) {
> >             return columnNames[col];
> >         }

> >         public Object getValueAt(int row, int col) {
> >             return data[row][col];
> >         }

> >         public Class getColumnClass(int c) {
> >             return getValueAt(0, c).getClass();
> >         }

> >         /*
> >          * Don't need to implement this method unless your table's
> >          * editable.
> >          */
> >         public boolean isCellEditable(int row, int col) {
> >             //Note that the data/cell address is constant,
> >             //no matter where the cell appears onscreen.
> >             if (col < 2) {
> >                 return false;
> >             } else {
> >                 return true;
> >             }
> >         }

> >         /*
> >          * Don't need to implement this method unless your table's
> >          * data can change.
> >          */
> >         public void setValueAt(Object value, int row, int col) {
> >             ...//debugging code not shown...
> >             ...//ugly special handling of Integers not shown...
> >             data[row][col] = value;
> >             fireTableCellUpdated(row, col);
> >             ...//debugging code not shown...
> >         }
> >         ...

### Detecting Data Changes

> A table and its model automatically detect whenever the user edits the table's data. However, if the data changes for another reason, you must take special steps to notify the table and its model of the data change. Also, if you don't implement a table model, as in `SimpleTableDemo`, then you must take special steps to find out when the user edits the table's data.

> An example of updating a table's data without directly editing it is in the BINGO application. The BINGO application, which is presented in BINGO!, has a table that displays some information about each user who is signed up to play the game. When a new user signs up to play BINGO, the table needs to add a new row for that user. More precisely, the table model needs to get the data for the new user, and then the table model needs to tell the table to display the new data.

> To notify the table model about a new user, the BINGO application invokes the table model's `updatePlayer` method. You can see the code for that method in `PlayerInfoModel`, which contains the implementation of the table model. The `updatePlayer` method records the new user's data and fires a table-model event. Because every table listens for table-model events from its model, the user-information table automatically detects the change and displays the new data.

> To fire the table-model event, the model invokes the `fireTableRowsInserted` method, which is defined by the `AbstractTableModel` class. Other `fireXxxx` methods that `AbstractTableModel` defines to help you fire table-model events are `fireTableCellUpdated`, `fireTableChanged`, `fireTableDataChanged`, `fireTableRowsDeleted`, `fireTableRowsInserted`, `fireTableRowsUpdated`, and `fireTableStructureChanged`.

> If you have a class such as `SimpleTableDemo` that isn't a table or table model, but needs to react to changes in a table model, then you need to do something special to find out when the user edits the table's data. Specifically, you need to register a table-model listener on the table model. Adding the bold code in the following snippet makes `SimpleTableDemo` react to table data changes.

> >     public class SimpleTableDemo ... implements TableModelListener {
> >         ...
> >         public SimpleTableDemo() {
> >             ...
> >     	model = table.getModel();
> >             model.addTableModelListener(this);
> >             ...
> >         }

> >         public void tableChanged(TableModelEvent e) {
> >             ...
> >             int row = e.getFirstRow();
> >             int column = e.getColumn();
> >             String columnName = model.getColumnName(column);
> >             Object data = model.getValueAt(row, column);

> >             ...// Do something with the data...
> >         }
> >         ...
> >     }

### Concepts: Cell Editors and Renderers

> Before you go on to the next few tasks, you need to understand how tables draw their cells. You might expect each cell in a table to be a component. However, for performance reasons, Swing tables aren't implemented that way.

> Instead, a single cell renderer is used to draw all of the cells in a column. Often, this cell renderer is shared between all columns that contain the same type of data. You can think of the renderer as a configurable ink stamp that the table uses to stamp appropriately formatted data onto each cell. When the user starts to edit a cell's data, a cell editor takes over the cell, controlling the cell's editing behavior.

> For example, each cell in the # of Years column in `TableDemo` contains `Number` data -- specifically, an `Integer` object. By default, the cell renderer for a `Number`-containing column uses a single `JLabel` instance to draw the appropriate numbers, right-aligned, on the column's cells. If the user begins editing one of the cells, the default cell editor uses a right-aligned `JTextField` to control the cell editing.

> To choose the renderer that displays the cells in a column, a table first determines whether the you specified a renderer for that particular column. (We'll tell you how to specify renderers a bit later.) If you didn't, then the table invokes the table model's `getColumnClass` method, which gets the data type of the column's cells. Next, the table compares the column's data type with a list of data types for which cell renderers are registered. This list is initialized by the table, but you can add to it or change it. Currently, tables put the following types of data in the list:

> - `Boolean` -- rendered with a check box.
> - `Number` -- rendered by a right-aligned label.
> - `ImageIcon` -- rendered by a centered label.
> - `Object` -- rendered by a label that displays the object's string value.

> The table chooses cell editors using a similar algorithm.

> Remember that if you let a table create its own model, it uses `Object` as the type of every column. `TableDemo.java` shows how to specify more precise column types.

> The next few sections tell you how to customize cell display and editing by specifying cell renderers and editors either by column or by data type,

### Validating User-Entered Text

> In the table examples you've seen so far, the user can enter any text into the # of Years column. `SimpleTableDemo` doesn't check the data's value, at all. The `TableDemo` example is slightly improved in that when the user is done editing, the code checks whether the entry can be parsed as an integer. However, `TableDemo` must use a bit of ugly code to convert the string returned by the default cell editor into an `Integer`. If it didn't do the conversion, then the actual type of the data would change from `Integer` to `String`.

> > 1.3 Note: As of v 1.3, the ugly conversion code is unnecessary because the default text cell editor automatically converts the data into the proper type.

> What we'd really like to do is to check the user's input while the user is typing, and to have the cell editor return an `Integer` instead of a string. You can accomplish one or both of these tasks by using a custom text field to control the cell editing.

> A custom text field can check the user's input either while the user is typing, or after the user has indicated the end of typing (such as by pressing return). We call these two types of checking change-validation and action-validation, respectively.

> The following code, taken from `TableEditDemo.java`, sets up a change-validated text field. The bold line of code makes the text field the editor for all columns that contain data of type `Integer`.

> >     final WholeNumberField integerField = new WholeNumberField(0, 5);
> >     integerField.setHorizontalAlignment(WholeNumberField.RIGHT);

> >     DefaultCellEditor integerEditor =
> >         new DefaultCellEditor(integerField) {
> >             //Override DefaultCellEditor's getCellEditorValue method
> >             //to return an Integer, not a String:
> >             public Object getCellEditorValue() {
> >                 return new Integer(integerField.getValue());
> >             }
> >         };
> >     table.setDefaultEditor(Integer.class, integerEditor);

> The `WholeNumberField` class used above is a custom `JTextField` subclass that allows the user to enter only digits. The `getValue` method returns the `int` value of the `WholeNumberField`'s contents. See How to Use Text Fields for more information about `WholeNumberField`. That section also provides a more general-purpose validating text field, called `DecimalField`, that you can customize so that it validates any number format that you specify.

### Using a Combo Box as an Editor

> Here is an example of setting up a combo box editor. The bold line of code sets up the combo box as the editor for a column, rather than for a specific data type.

> >     TableColumn sportColumn = table.getColumnModel().getColumn(2);
> >     ...
> >     JComboBox comboBox = new JComboBox();
> >     comboBox.addItem("Snowboarding");
> >     comboBox.addItem("Rowing");
> >     comboBox.addItem("Chasing toddlers");
> >     comboBox.addItem("Speed reading");
> >     comboBox.addItem("Teaching high school");
> >     comboBox.addItem("None");
> >     sportColumn.setCellEditor(new DefaultCellEditor(comboBox));

> Here is a picture of the combo box editor in use:

> The combo box editor is implemented in `TableRenderDemo.java`, which is discussed some more in Further Customizing Table Display and Event Handling.

### Specifying Other Editors

> As the previous sections showed, you can set the editor for an entire column using the `TableColumn` `setCellEditor` method, or for a specific type of data using the `JTable` `setDefaultEditor` method. For both methods, you must specify an argument that implements the `TableCellEditor` interface. Fortunately, the `DefaultCellEditor` class implements this interface and provides constructors to let you specify an editing component that's a `JTextField`, `JCheckBox`, or `JComboBox`. You usually don't have to explicitly specify a check box as an editor, since columns with `Boolean` data automatically use a check box renderer and editor.

> What if you want to specify an editor that isn't a text field, check box, or combo box? Well, because `DefaultCellEditor` doesn't support other types of components, you must do a little more work. You need to create a subclass of the desired editor component, and the subclass must implement the `TableCellEditor` interface. Then you set up the component as an editor for a data type or column, using the `setDefaultEditor` or `setCellEditor` method, respectively.

> > 1.3 Note: The `AbstractCellEditor` class, which was added in v 1.3, makes it much easier to add support for non-standard editor components. We plan to add an example of using it. For now, you can find information in the JTable release document and the API documentation for `AbstractCellEditor`.

> Here is a picture of a table with a dialog that serves, indirectly, as a cell editor. When the user begins editing a cell in the Favorite Color column, a button (the true cell editor) appears and brings up the dialog, with which the user can choose a different color.

> You can find the code in `TableDialogEditDemo.java`. The example also requires `WholeNumberField.java`.

### Further Customizing Table Display and Event Handling

> You've already seen how to specify cell editors. You can also specify renderers for cells and for column headers. Customizing renderers lets you display data in custom ways and specify tool tip text for the table to display.

> Although renderers determine how each cell or column header looks, they don't handle events. To pick up the events that take place inside a table, you should choose the appropriate technique for the sort of event you're interested in. For a cell that's being edited, the editor should process events. To detect row/column/cell selections and deselections, use a selection listener as described in Detecting User Selections. To detect mouse clicks on a column header, you can register a mouse listener on the table header. (See `TableSorter.java` for an example.) To detect other events, you can register the appropriate listener on the `JTable` object.

> Creating a custom renderer can be as easy as creating a subclass of an existing component and then implementing the single method in the `TableCellRenderer` interface. In the preceding figure, the color renderer used for Favorite Color cells is a subclass of `JLabel`. You can find the code for the renderer in the `ColorRenderer` inner class in `TableDialogEditDemo.java`. Here is the code that registers a `ColorRenderer` instance as the default renderer for all `Color` data:

> >     table.setDefaultRenderer(Color.class, new ColorRenderer(true));

> You can even specify a cell-specific renderer, if you like. To do this, you need to define a `JTable` subclass that overrides the `getCellRenderer` method. For example, the following code makes the first cell in the first column of the table use a custom renderer:

> >     TableCellRenderer weirdRenderer = new WeirdRenderer();
> >     table = new JTable(...) {
> >         public TableCellRenderer getCellRenderer(int row, int column) {
> >     	if ((row == 0) && (column == 0)) {
> >     	    return weirdRenderer;
> >     	}
> >     	// else...
> >     	return super.getCellRenderer(row, column);
> >         }
> >     };

> To add tool tips to cells or column headers, you need to get or create the cell or header renderer, and then use the `setToolTipText` method of the renderer's component. `TableRenderDemo.java` adds tool tips to both the cells and header for the Sport column with the following code:

> >     //Set up tool tips for the sport cells.
> >     DefaultTableCellRenderer renderer =
> >             new DefaultTableCellRenderer();
> >     renderer.setToolTipText("Click for combo box");
> >     sportColumn.setCellRenderer(renderer);

> >     //Set up tool tip for the sport column header.
> >     TableCellRenderer headerRenderer = sportColumn.getHeaderRenderer();
> >     if (headerRenderer instanceof DefaultTableCellRenderer) {
> >         ((DefaultTableCellRenderer)headerRenderer).setToolTipText(
> >                  "Click the sport to see a list of choices");
> >     }

> > 1.3 Note: In the 1.3 version of the Java 2 platform, the `getHeaderRenderer` method returns `null` by default. To find the default header renderer, you instead use the new `getDefaultRenderer` method, which is defined in `JTableHeader`. For example, in the preceding snippet the red-colored code should be changed to this:

> > >     TableCellRenderer headerRenderer = table.getTableHeader().
> > >             getDefaultRenderer();

> > You can find the 1.3 version of `TableRenderDemo.java` in `example-1dot3/TableRenderDemo.java`.

> An interesting feature of `TableRenderDemo` is how it determines the sizes of its columns. For each column, `TableRenderDemo` gets the components used to render that column's header and cells. It then asks the components how much space they need. Finally, it uses the space information to set the column's width.

> >     TableColumn column = null;
> >     Component comp = null;
> >     int headerWidth = 0;
> >     int cellWidth = 0;
> >     Object[] longValues = model.longValues;

> >     for (int i = 0; i < 5; i++) {
> >         column = table.getColumnModel().getColumn(i);

> >         comp = column.getHeaderRenderer().
> >                          getTableCellRendererComponent(
> >                              null, column.getHeaderValue(),
> >                              false, false, 0, 0);
> >         headerWidth = comp.getPreferredSize().width;

> >         comp = table.getDefaultRenderer(model.getColumnClass(i)).
> >                          getTableCellRendererComponent(
> >                              table, longValues[i],
> >                              false, false, 0, i);
> >         cellWidth = comp.getPreferredSize().width;
> >         ...//debugging code not shown...
> >         column.setPreferredWidth(Math.max(headerWidth, cellWidth));
> >     }

> >     ...//In the model:
> >     public final Object[] longValues = {"Angela", "Andrews",
> >                                         "Teaching high school",
> >                                         new Integer(20), Boolean.TRUE};

> > 1.3 Note: Because the 1.3 `getHeaderRenderer` method returns `null` by default, you generally use the 1.3 `getDefaultRenderer` method instead. For example, the red code from the previous snippet would be replaced with this:

> > >         table.getTableHeader().getDefaultRenderer()

> > You can find the 1.3 version of `TableRenderDemo.java` in `example-1dot3/TableRenderDemo.java`.

### Sorting and Otherwise Manipulating Data

> One way to perform data manipulation such as sorting is to use one or more specialized table models (data manipulators), in addition to the table model that provides the data (the data model). The data manipulators should sit between the table and the data model, as the following picture shows:

> You can use the `TableMap` and `TableSorter` classes when implementing your data manipulator. `TableMap.java` implements `TableModel` and serves as a superclass for data manipulators. `TableSorter.java` is a `TableMap` subclass that sorts the data provided by another table model. You can either change these classes, using them as a basis for writing your own data manipulator, or use the classes as-is to provide sorting functionality.

> To implement sorting with `TableSort`, you need just three lines of code. The following listing shows the differences between `TableDemo` and its sorting cousin, `TableSorterDemo.java`.

> >     TableSorter sorter = new TableSorter(myModel); //ADDED THIS
> >     //JTable table = new JTable(myModel);          //OLD
> >     JTable table = new JTable(sorter);             //NEW
> >     sorter.addMouseListenerToHeaderInTable(table); //ADDED THIS

> The `addMouseListenerToHeaderInTable` method adds a mouse listener that detects clicks over the column headers. When the listener detects a click, it sorts the rows based on the clicked column. As the following snapshot shows, when you click "Last Name", the rows are reordered so that the row with "Andrews" becomes the first row. When you Shift-click a column header, the rows are sorted in reverse order.

### The Table API

> The tables in this section cover just part of the table API. For more information about the table API, see the API documentation for `JTable` and for the various classes and interfaces in the table package. Also see The JComponent Class, which describes the API that `JTable` inherits from `JComponent`. The API for using tables falls into the following categories:
> - Table-Related Classes and Interfaces
> - Creating and Setting Up a Table
> - Manipulating Columns
> - Using Editors and Renderers
> - Implementing Selection

> Table-Related Classes and Interfaces
> Class/Interface | Purpose
> --- | ---
> `JTable` | The component that presents the table to the user.
> ``JTableHeader`` | The component that presents the column names to the user. By default, the table generates this component automatically.
> `TableModel`, `AbstractTableModel` | Respectively, the interface that a table model must implement and the usual superclass for table model implementations.
> ``TableCellRenderer`, ``DefaultTableCellRenderer``` | Respectively, the interface that a table cell renderer must implement and the usual implementation used.
> `TableCellEditor`, ``DefaultCellEditor`` | Respectively, the interface that a table cell editor must implement and the usual implementation used.
> ``TableColumnModel``, `DefaultTableColumnModel` | Respectively, the interface that a table column model must implement and the usual implementation used. You don't usually need to deal with the table column model directly unless you need to get the column selection model, or get a column index or object.
> `TableColumn` | Controls all the attributes of a table column, including resizability; minimum, preferred, current, and maximum widths; and an optional column-specific renderer/editor.
> ``DefaultTableModel`` | A `Vector`-based table model used by `JTable` when you construct a table specifying no data model and no data.

> Creating and Setting Up a Table
> `JTable` Constructor/Method | Purpose
> --- | ---
> `JTable(TableModel) JTable(TableModel, TableColumnModel) JTable(TableModel, TableColumnModel, ListSelectionModel) JTable() JTable(int, int) JTable(Object[][], Object[]) JTable(Vector, Vector)` | Create a table. The optional `TableModel` argument specifies the model that provides the data to the table. The optional `TableColumnModel` and `ListSelectionModel` arguments let you specify the table column model and the row selection model. As an alternative to specifying a table model, you can supply data and column names, using arrays or vectors. Another option is to specify no data, optionally specifying the number of rows and columns (both integers) to be in the table.
> `void setPreferredScrollableViewportSize( Dimension)` | Set the size of the visible part of the table when it's viewed within a scroll pane.
> `JTableHeader getTableHeader(Dimension)` | Get the component that displays the column names.

> Manipulating Columns
> Constructor/Method | Purpose
> --- | ---
> `TableColumnModel getColumnModel()` (in `JTable`) | Get the table's column model.
> `TableColumn getColumn(int) Enumeration getColumns()` (in `TableColumnModel`) | Get one or all of the `TableColumn` objects for the table.
> `void setMinWidth(int) void setPreferredWidth(int) void setMaxWidth(int)` (in `TableColumn`) | Set the minimum, preferred, or maximum width of the column.
> `int getMinWidth(int) int getPreferredWidth() int getMaxWidth() int getWidth()` (in `TableColumn`) | Get the minimum, preferred, maximum, or current width of the column.

> Using Editors and Renderers
> Method | Purpose
> --- | ---
> `void setDefaultRenderer(Class, TableCellRenderer) void setDefaultEditor(Class, TableCellEditor)` (in `JTable`) | Set the renderer or editor used, by default, for all cells in all columns that return objects of the specified type.
> `void setCellRenderer(TableCellRenderer) void setCellEditor(TableCellEditor)` (in `TableColumn`) | Set the renderer or editor used for all cells in this column.
> `TableCellRenderer getHeaderRenderer()` (in `TableColumn`) | Get the header renderer for this column, which you can then customize.

> Implementing Selection
> `JTable` Method | Purpose
> --- | ---
> `void setSelectionMode(int)` | Set the selection intervals allowed in the table. Valid values are defined in `ListSelectionModel` as `SINGLE_SELECTION`, `SINGLE_INTERVAL_SELECTION`, and `MULTIPLE_INTERVAL_SELECTION` (the default).
> `void setSelectionModel(ListSelectionModel) ListSelectionModel getSelectionModel()` | Set or get the model used to control row selections.
> `void setRowSelectionAllowed(boolean) void setColumnSelectionAllowed(boolean) void setCellSelectionEnabled(boolean)` | Set the table's selection orientation. The boolean argument specifies whether that particular type of selection is allowed. By default, row selection is allowed, and column and cell selection are not.

### Examples that Use Tables

> This table lists examples that use `JTable` and where those examples are described.

> Example | Where Described | Notes
> --- | --- | ---
> `SimpleTableDemo` | Creating a Simple Table | A basic table with no custom model. Does not include code to specify column widths or detect user editing.
> `SimpleTable- SelectionDemo` | Detecting User Selections | Adds single selection and selection detection to `SimpleTableDemo`. By modifying the program's `ALLOW_COLUMN_SELECTION` and `ALLOW_ROW_SELECTION` constants, you can experiment with alternatives to the table default of allowing only rows to be selected.
> `TableDemo` | Creating a Table Model | A basic table with a custom model.
> `TableEditDemo`, `WholeNumberField.java` | Validating User-Entered Text | Modifies `TableDemo` to use a custom editor (a text field variant) for all `Integer` data.
> `TableRenderDemo` | Using a Combo Box as an Editor, Further Customizing Table Display and Event Handling | Modifies `TableDemo` to use a custom editor (a combo box) for all data in the Sport column. Also intelligently picks column sizes. Uses renderers to display tool tips for the Sport column (both cells and header).
> `TableDialogEditDemo`, `WholeNumberField.java` | Specifying Other Editors | Modifies `TableEditDemo` to have a cell renderer and editor that display a color and let you choose a new one, using a color chooser dialog.
> `TableSorterDemo` | Sorting and Otherwise Manipulating Data | Sorts column data by interposing a data manipulating table model between the data model and the table. Detects user clicks on column headers.
> `ListSelectionDemo` | How to Write a List Selection Listener | Shows how to use all list selection modes, using a list selection listener that's shared between a table and list.
> `SharedModelDemo` | Nowhere | Builds on `ListSelectionDemo` making the data model be shared between the table and list. If you edit an item in the first column of the table, the new value is reflected in the list.
> TreeTable, TreeTable II | Creating TreeTables in Swing, Creating TreeTables: Part 2 | Examples that combine a tree and table to show detailed information about a hierarchy such as a file system. The tree is a renderer for the table.

| Start of Tutorial > Start of Trail > Start of Lesson | Search Feedback Form

Copyright 1995-2001 Sun Microsystems, Inc. All rights reserved.