JTable
Whereas the JList class displayed a list of items in a single column, the JTable class is capable of showing items that each have several columns. You need to attach a TableModel object (which references the item data) to the JTable. The most common way of doing this is to subclass the AbstractTableModel class and override three methods that provide the total number of rows, the total number of columns, and the object at a particular row/column intersection, or "cell".
Continuing the simple examples from earlier, where you are using the strings "Red", "Green" and "Blue", assume you want a three-column table where the first column will be the normal text of the colour, the second column the text in upper-case, and the third column the number of characters in the word. Define the following inner class inside DemoUI, and note that you need to import package java.swing.table:
The class ColourTableModel extends the Java supplied AbstractTableModel
The constructor is identical to that used for ColourListModel – it adds the three strings to an ArrayList object
The getRowCount() method returns the total number of rows in the table, which will correspond to the total number of items in the ArrayList object
The getColumnCount() method returns the total number of columns in the table, which in this case is three
The getValueAt() method provides two arguments, being the row index and the column index, where each of them starts from zero. You can think of a table as being like a spreadsheet, where the row and column indexes together point to a particular cell. The method does the following:
- Retrieves the text from the
ArrayListobject using the specified row index - If the column index is zero then the first column in wanted, so just return the text as-is
- If the column index is one then the second column in wanted, so return the text converted to upper-case
- If the column index is two then the third column in wanted, so return the number of characters in the text
- Because a
switchstatement was used to determine the column index the compiler will check that something is being returned in all cases, including those wherecolumnIndexis not 0, 1 or 2. Even though this should never happen (because thegetColumnCount()method returns 3) the compiler does not know this so you need to specify a default processing for all other cases. In this case you simply throw an unchecked exception
Now in the buildUI() method of the main body of DemoUI you can instantiate a ColourTableModel object, assign it to a new JTable object, put the table in a scroll pane and place it on the panel:
The JTable object takes care of invoking the appropriate ColourTableModel methods for you automatically. You should see the following table displayed:
There are a couple of points to note about the table as it stands:
- Because you have not specifically set the column headings it has defaulted to spreadsheet-style names of A, B, C etc.
- All items of data are left-aligned. While this is a sensible default for strings, numbers generally look better when right aligned
To set the column headers you can override the getColumnName() method inside the ColourTableModel inner class:
To make numbers right-aligned you can take advantage of the fact that tables are capable of using default alignments based upon the class of the Object which is returned by getValueAt(). To do this, override the getColumnClass() method inside ColourTableModel:
- The
getValueAt()method is called using the specified column index on row zero to determine the object which appears there. ThegetClass()method is then obtained from that object and returned. The table now has the information it needs to render the alignment sensibly
The table should now look as follows:
If you would like users to be able to sort the data on any of the columns, you can add the following statement after you instantiate the JTable object:
The user can now click on any column header to sort the table by that column. Each time a column is clicked it toggles between being sorted in ascending and descending sequence. A small arrow appears in the column heading to indicate the sequencing.
It's possible to enable table cells to be directly edited by the user. Suppose, for example, you want to enable the text of the colour to be edited in the first column. Because the values displayed in columns two and three depend on the text in column one then only column one should be editable. First, you need to override the isCellEditable() method inside ColourTableModel:
- The method needs to return
trueif the cell should be editable and false otherwise. Above,truewill be returned whenever the column index is zero
If you run the application, you can now double-click inside any entry in the first column to make the cell go into edit mode:
Try changing the text to something else and press Enter on your keyboard. You will notice the text revert to what it was previously! To save the edited change you need to override the setValue() method as well:
- Because your model data is being stored in the
ArrayListobject calledcolours, the method firstly removes the old value there at the modified row index and then adds the new value at the same position.
If you run the application again your change is made but you will notice that the upper-case version and number of characters in the second and third columns have not been updated. You can fix this by adding one more statement to the above method to tell the table that the data has been modified so that it can perform a refresh: