Brought to you by EarthWeb
ITKnowledge Logo Login Graphic Click Here!
Click Here!
ITKnowledge
Search this book:
 
Search the site:
 
EXPERT SEARCH ----- nav

EarthWeb Direct

EarthWeb Direct

EarthWeb sites: other sites

Previous Table of Contents Next


The order of the columns in the TableColumnModel does not have to coincide with the order in the data model. This allows different tables to view the same model data in different orders or different sets of columns from the data model. The methods convertColumnIndexToModel and covertColumnIndexToView in the JTable class can be used to map from the view’s coordinate space to the models, and vice versa.

The columnAtPoint method can be used to determine which column lies below a point. This is often used for hit detection in mouse listeners added to the table.

The TableColumn class goes against the general design of the JTable class, that being that the interaction between the various table components is defined in an interface and a default implementation for the interface is provided. However, TableColumn is a class. This makes it more difficult to replace with a custom implementation than if TableColumn were an interface and the implementation contained in a DefaultTableColumn class, as was seen earlier in this chapter for the TableColumnModel interface and its default implementation, the DefaultTableColumnModel class.

Pulling It All Together: A JTable Example

The table presented by the SimpleTableTest application did, in fact, present the data passed to the constructor. However, with a little extra effort, the JTable component can yield a much nicer display. This section will present a custom data model, renderers, and editors that combine to make a complete table. The example code for each portion of the table will be given as it is presented. The source listing that can be compiled and executed for the example will be presented in its entirety at the end of the section.

The default renderer for the table calls the toString method of the Object being rendered. For the second and third columns in the SimpleTableTest application, a more appropriate rendering would be color coded for column two and a check box for column three. There are multiple ways to accomplish this goal. You can add a custom renderer to the TableColumn instance that represents columns two and three in the ColumnModel. However, that is not the approach taken here. Instead, a renderer will be registered with the table for each class that requires custom rendering. This allows the same renderer to be shared by multiple columns in a table if they each contain the same class of data.

The first step is to define an extension to the AbstractTableModel class that has a more intimate understanding of the data it contains than results from passing a Vector or array to the JTable class’s constructor. The TableTestModel class shown in Listing 12.6 is such a class (Figure 12.6 shows the output from this listing). Internally, this class stores its data in a two-dimensional array. The design of the data model is such that the name column is not editable, but the other columns are. This information is obtained by clients of the model via the isCellEditable method. If the column index passed to this function is 0, false is returned. true is returned for all other columns. The row parameter is not used in this method. The model also protects against the name being set in the setValueAt method. If a column index of 0 is passed to this method, a RuntimeException is thrown, and the data in the model is not altered. The model returns the proper Class for the data stored in each column from the getColumnClass method. This is possible for this data model, because the data in every cell in a column is of the same type. If this is not the case, the getColumnClass method must return a common ancestor of the classes contained in the column. This can be the Object class itself.


Figure 12.6  The TestTableModel used as a JTable data model.

The structure of the TableTestModel is static. Thus, the only time the data in the model changes is in the setValueAt method. This method calls the fireTableCellUpdated method inherited from the AbstractTableModel class to notify listeners when a value changes. If this model is shared between multiple tables, edits in one table are displayed in the other tables after the update event is received. The data model can use the other convenience methods inherited from the AbstractTableModel class if rows are added or deleted from the model or other structure changes in the model are allowed.

Listing 12.6 The TableTestModel Class

/**
 * Table model that returns the Class of the data in
 * a particular column. This allows the table to set
 * renderers for the data.
 **/
class TableTestModel extends AbstractTableModel {

    /**
     * The data in the model.
     **/
     Object[][] data = {
        { “Mike”, Color.blue, new Boolean( true ), new Integer(9) },
        { “Mari”, Color.red, new Boolean( true ), new Integer(6) },
        { “Molly”, Color.yellow, new Boolean( false ), new Integer(1) },
        { “Betsy”, Color.orange, new Boolean( false ), new Integer(8) },
        { “Bobby”, Color.lightGray, new Boolean( true ), new Integer(7) }
        };

    /**
     * The column names for the model.
     **/
    String[] columnNames = { “Name”, “Color”, “Enabled”, “Size” };

    /**
     * TableTestModel, constructor.
     **/
    TableTestModel() {
        super();
    }

    /**
     * getRowCount, from TableModel.
     *
     * @return The number of rows in the data.
     **/
    public int getRowCount() {
        return( data.length );
    }

    /**
     * getColumnCount, from TableModel.
     *
     * @return The number of columns in the data.
     **/
    public int getColumnCount() {
        return( data[0].length );
    }

    /**
     * getValueAt, from TableModel.
     *
     * @param row The row of the requested data object.
     * @param column The column of the requested data object.
     * @return The object at the specified cell.
     **/
    public Object getValueAt( int row, int column ) {
        return( data[ row ][ column ] );
    }

    /**
     * setValueAt, from TableModel.
     *
     * Set the data value in the given location to the
     * given object.
     *
     * @param value The new data object.
     * @param row The row of the new data object.
     * @param column The column of the new data object.
     **/
    public void setValueAt( Object value, int row, int column ) {
        if( column == 0 )
            throw new RuntimeException(
                       “The Name column is not editable” );
        data[ row ][ column ] = value;
    }

    /**
     * getColumnName, from TableModel.
     *
     * @param column The column index whose name is desired.
     * @return The name of the column with the given index.
     **/
    public String getColumnName( int column ) {
        return( columnNames[ column ] );
    }

    /**
     * getColumnClass, from TableModel.
     *
     * @param column The column index whose Class is desired.
     * @return The Class of the data for the column with the given index.
     **/
    public Class getColumnClass( int column ) {
        return( data[0][ column ].getClass() );
    }

    /**
     * isCellEditable, from TableModel.
     *
     * All columns except the first are editable in this model.
     *
     * @param row The row of the cell whose editability is requested.
     * @param column The column of the cell whose editability
     *               is requested.
     * @return true if the cell is editable, false otherwise.
     **/
    public boolean isCellEditable( int row, int column ) {
        if( column == 0 ) {
            return( false );
        } else {
            return( true );
        }
    }
}


Previous Table of Contents Next
HomeAbout UsSearchSubscribeAdvertising InfoContact UsFAQs
Use of this site is subject to certain Terms & Conditions.
Copyright (c) 1996-1999 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.