15.1 The JTable Class


Before we get ahead of ourselves, let's look at the JTable class and its supporting cast members.

15.1.1 Table Columns

With Swing tables, the basic unit is not an individual cell but a column. Most columns in real-world tables represent a certain type of information that is consistent for all records. For example, a record containing a person's name is a String and might be the first column of the table. For every other record (row), the first cell is always a String. The columns do not need to all have the same data type. The same record could hold not only a person's name, but whether or not they owned a computer. That column would hold Boolean values, not String values. The models supporting JTable reflect this view of the world. There is a TableModel that handles the contents of each cell in the table. You will also find a TableColumnModel that tracks the state of the columns in the table (how many columns, the total width, whether or not you can select columns, etc.).

The ability to store different types of data also affects how the table draws the data. The table column that maps to the "owns a computer" field could use a JCheckBox object for the cells of this column while using regular JLabel objects for the cells of other columns. But again, each column has one data type and one class responsible for drawing it.

Now, as the JTable class evolves, you may find alternate ways to think about tables without relying so heavily on columns. You'll want to keep an eye on the API in future releases of the Swing package. Figure 15-2 shows how the classes of the JTable package fit together.

Figure 15-2. JTable class diagram
figs/swng2.1502.gif

Well, we made it this far without officially discussing the JTable class itself. Dynamic data and database queries are handled entirely by the table model underneath the display. So what can you do with a JTable object? The JTable class gives you control over the appearance and behavior of the table. You can control the spacing of columns, their resizability, their colors, and so on. The JTable object is the source of row selections. Through delegation, you can add and remove rows and columns directly with the JTable object.

15.1.2 Properties

The appearance of a JTable is manipulated almost entirely through its properties. To make things a bit more manageable, we'll break the properties up into three smaller tables: one for row, column, and cell properties; one for selection properties; and one for visual properties. Table 15-1 covers the row, column, and cell properties.

Table 15-1. JTable row, column, and cell properties

Property

Data type

get

is

set

Default value

autoCreateColumnsFromModel

boolean

·

 

·

false

autoResizeMode

int

·

 

·

AUTO_RESIZE_ALL_COLUMNS

columnCount

int

·

   

0

columnModel

TableColumnModel

·

 

·

DefaultTableColumnModel( )

model

TableModel

·

 

·

DefaultTableModel( )

rowCount

int

·

   

0

rowHeight

int

·

 

·

16

The autoCreateColumnsFromModel property determines whether the column model is loaded automatically with data from the table model. This value is set to true if you don't supply a non-null ColumnModel to the constructor. (You can always replace an existing column model with the setColumnModel( ) method.) The autoResizeMode property determines how the table reacts to being resized. Using the constants presented in Table 15-4, you can adjust all of the columns, only the last column, or shut resizing off altogether. You must turn off autoresizing if you want to use the horizontal scrollbar in your scroll pane. The columnCount and rowCount properties allow you to ask the JTable object how many rows and columns it has. These values come from the models in place. The columnModel property holds the current column model and can be replaced at runtime, if necessary. The rowHeight property dictates how tall rows are, in pixels. This property must be a number greater than or equal to one. Other values cause the setRowHeight( ) method to throw an IllegalArgumentException. The value of rowHeight includes the vertical intercell spacing.

Table 15-2 lists the selection-related properties of the JTable class. The selectionModel property holds the ListSelectionModel object that handles row selections, and the selectionMode property applies to that model. (You can control the column selections with the selectionModel property of the TableColumnModel for your table.) The cellSelectionEnabled , columnSelectionAllowed, and rowSelectionAllowed properties determine whether you can select cells, columns, or rows. If cells are selectable, only cells can be selected, regardless of the row and column properties. With cell selection turned on and row and column selection turned off, you can still select a range of cells. With an active selection on your table, the selectedColumn , selectedColumnCount, selectedColumns, selectedRow, selectedRowCount, and selectedRows give you access to the various parts of that selection. The selectedRow and selectedColumn properties store the anchor selection (i.e., the first selection) from their respective selection models.

Table 15-2. JTable selection properties

Property

Data type

get

is

set

Default value

cellSelectionEnabled

boolean

·

 

·

false

columnSelectionAllowed

boolean

·

 

·

false

rowSelectionAllowed

boolean

·

 

·

true

selectedColumn

int

·

   

-1

selectedColumnCount

int

·

   

0

selectedColumns

int[]

·

   

int[0]

selectedRow

int

·

   

-1

selectedRowCount

int

·

   

0

selectedRows

int[]

·

   

int[0]

selectionMode

int

   

·

MULTIPLE_INTERVAL_SELECTION

selectionModel

ListSelectionModel

·

 

·

DefaultListSelectionModel

Table 15-3 covers the remaining properties of the JTable class. The cellEditor property determines the cell editor currently in use. When you start editing, the JTable class looks up your column and asks it for an editor. If the column has one, that editor is used; otherwise, a default editor for the column's class type is used. If no cell is currently being edited, this property is null. If you want your table to support automatic drag initiation, set the dragEnabled property to true. The gridColor , selectionBackground, and selectionForeground properties determine the color used for the grid lines and selection text. The intercellSpacing property determines the horizontal and vertical spacing around each cell in the table. The preferredScrollableViewportSize property determines the preferred size of the scrollpane for the table. The scrollableTracksViewportHeight and scrollableTracksViewportWidth properties are always false, which indicates that making the viewport around the table should not resize the table to fit the viewport (assuming you have placed the table in a scrollpane). You can control which lines show up on the table with showGrid , showHorizontalLines, and showVerticalLines. Use setShowGrid( ) as a convenient way to turn both horizontal and vertical lines on or off at the same time. The tableHeader property is used to store a JTableHeader object for your table. This header can be used in a JScrollPane as the column header for your table. (No row header counterpart is provided, but you can see an example of creating one in the next chapter.) The rowMargin property determines the amount of empty space between rows. This is really just a more convenient way of getting at the height information in the intercellSpacing property.

Table 15-3. JTable visual and editing properties

Property

Data type

get

is

set

Default value

accessibleContexto

AccessibleContext

·

   

JTable.AccessibleJTable

cellEditor

TableCellEditor

·

 

·

null

dragEnabled1.4

boolean

·

 

·

false

gridColor

Color

·

 

·

From L&F

intercellSpacing

Dimension

·

 

·

Dimension(1, 1)

preferredScrollableViewportSizeo

Dimension

·

 

·

Dimension(450, 400)

rowMargin

int

·

 

·

1

scrollableTracksViewportHeighto

boolean

·

   

false

scrollableTracksViewportWidtho

boolean

·

   

false

selectionBackgroundb

Color

·

 

·

From L&F

selectionForegroundb

Color

·

 

·

From L&F

showGrid

boolean

   

·

true

showHorizontalLines

boolean

·

 

·

true

showVerticalLines

boolean

·

 

·

true

tableHeader

JTableHeader

·

 

·

JTableHeader(column-Model)

UIb

TableUI

·

 

·

From L&F

UIClassIDo

String

·

   

"TableUI"

bbound, ooverridden, 1.4since 1.4

See also properties from the JComponent class (Table 3-6).

15.1.2.1 Examples

To see some of the more interesting properties in action, the following example sets up a simple (contrived) data set. We shut off autoresizing so that horizontal scrolling works properly. We also set the selection mode so that any range of cells can be selected. (We'll look at responding to selection events in the next section.)

Figure 15-3. A simple JTable in a JScrollPane with a range of cells selected
figs/swng2.1503.gif

Here's the source code that built the table in Figure 15-3:

// TableFeature.java // A test of the JTable class using default table models and a convenience  // constructor // import java.awt.*; import javax.swing.*; import java.util.Date; import java.io.File; public class TableFeature extends JFrame {   String titles[] = new String[] {     "Directory?", "File Name", "Read?", "Write?", "Size", "Last Modified"   };   public TableFeature( ) {     super("Simple JTable Test");     setSize(300, 200);     setDefaultCloseOperation(EXIT_ON_CLOSE);     File pwd = new File(".");     Object[][] stats = getFileStats(pwd);     JTable jt = new JTable(stats, titles);     jt.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);     jt.setColumnSelectionAllowed(true);     JScrollPane jsp = new JScrollPane(jt);     getContentPane( ).add(jsp, BorderLayout.CENTER);   }   public Object[][] getFileStats(File dir) {     String files[] = dir.list( );     Object[][] results = new Object[files.length][titles.length];     for (int i=0; i < files.length; i++) {       File tmp = new File(files[i]);       results[i][0] = new Boolean(tmp.isDirectory( ));       results[i][1] = tmp.getName( );       results[i][2] = new Boolean(tmp.canRead( ));       results[i][3] = new Boolean(tmp.canWrite( ));       results[i][4] = new Long(tmp.length( ));       results[i][5] = new Date(tmp.lastModified( ));     }     return results;   }   public static void main(String args[]) {     TableFeature tf = new TableFeature( );     tf.setVisible(true);   } }

15.1.3 Events

All table-specific events you would expect to see from the JTable class are routed through its data and column models. You must get a reference to these models and attach listeners to the models directly, with code like this example, which uses our custom EEL utility discussed in Chapter 3:

TableModel myModel = new MyTableModel( );  // Some valid TableModel class JTable table = new JTable(myModel); EEL eel = EEL.getInstance( ); eel.addGui( ); // Listen for added/removed/updated rows. myModel.addTableModelListener(eel); TableColumnModel columnModel = table.getColumnModel( ); // Listen for added/removed/moved columns. columnModel.addTableColumnModelListener(eel); // Listen for row selections. myTable.getSelectionModel( ).addListSelectionListener(eel); // Listen for column selections. columnModel.getSelectionModel.addListSelectionListener(eel);

You can see a more detailed example using the selection listeners later in this chapter. Examples using model listeners appear in Chapter 16.

15.1.4 Constants

Table 15-4 shows the constants defined in JTable. These constants specify how columns behave when you resize the entire table or adjust a single column; they are used for the autoResizeMode property.

Table 15-4. JTable constants

Constant

Data type

Description

AUTO_RESIZE_ALL_COLUMNS

int

When a table is resized, all columns are resized proportionately.

AUTO_RESIZE_LAST_COLUMN

int

When a table is resized, resize the last column only.

AUTO_RESIZE_NEXT_COLUMN

int

When a column is resized, resize the next column too. For example, if you make column N bigger, column N+1 shrinks.

AUTO_RESIZE_OFF

int

When a table is resized, do not resize the columns at all.

AUTO_RESIZE_SUBSEQUENT_COLUMNS

int

When a column is resized, resize all subsequent columns proportionally to preserve the overall width of the table.

15.1.5 Constructors

public JTable( )

Create a new JTable object using a DefaultTableModel, a DefaultTableColumnModel, and a DefaultListSelectionModel for its models.

public JTable(TableModel dm)
public JTable(TableModel dm, TableColumnModel cm)
public JTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm)

These constructors allow you to specify the exact table model, table column model, and (row) list selection model you want to use. If you want to specify only the column or list selection model, you can pass null as an argument for the other models, and the appropriate default model is created and used.

public JTable(int numRows, int numColumns)

This constructor builds a default table model with the specified number of rows and columns. Default table column and list selection models are also used.

public JTable(Vector data, Vector columnNames)
public JTable(Object data[][], Object columnNames[])

Populate tables by filling the custom table model with data and naming the columns with columnNames. In the case of the first constructor, it is assumed that the data vector is a vector containing other vectors, one for each row of data. The data argument can contain any type of object. The table does its best to render the objects in the array appropriately, using labels generated by calling toString( ) on the objects if necessary. While the columnNames argument can also contain an array of any type of object, a String[] is the most common. The default table header renderer uses column names (or the toString( ) result of nonstring objects) to label columns.

The table models used by these constructors are not instances of DefaultTable-Model. If you retrieve the table model, you can interact with it only through the TableModel interface.

15.1.6 Other Interesting Methods

Here are a few other methods to remember. These methods allow you to control tables programmatically. If you have other buttons or keyboard shortcuts for things like selecting matching records, these methods come in handy.

public void addColumnSelectionInterval(int index0, int index1)
public void addRowSelectionInterval(int index0, int index1)

Programmatically extend the column and row selections on the table. Discontiguous selections must be added as separate contiguous intervals. The value of index0 does not have to be less than or equal to index1, but an IllegalArgumentException results if either index is outside the range of valid columns.

public void clearSelection( )

This method removes all selection intervals (both rows and columns) currently active in the table.

public int columnAtPoint(Point p)

Given an (x,y) coordinate p relative to the upper-left corner of this JTable component, return the column that contains that point. (This method returns -1 if p is not contained by any of the table's columns.) Along with the rowAtPoint( ) method, you can take advantage of this method to track where the mouse is in the table.

public boolean editCellAt(int row, int col, EventObject event)

Open the cell at (row, col) for editing. Fancy editors can alter their behavior or appearance based on the initiating action passed as event. If you do not require a specific event, you can create a simple MouseEvent of type MOUSE_CLICKED with a click count of 2.

public void moveColumn(int column, int targetColumn)

This method relocates the column at index column to become the column at index targetColumn. This comes in handy if you have layout wizards that allow users to organize the columns separate from the table itself.

public void removeColumn(TableColumn column)

This method allows you to completely delete a column.

public void removeColumnSelectionInterval(int index0, int index1)
public void removeRowSelectionInterval(int index0, int index1)

Subtract a selection interval (columns or rows, respectively) from the active selection. This action is not the same as clearing the selection. If the current selection has more items than you remove, the remaining items stay selected.

public int rowAtPoint(Point p)

Given an (x,y) coordinate p relative to the upper-left corner of this JTable component, return the row that contains that point. (This method returns -1 if p is not contained by any of the table's rows.) Along with the columnAtPoint( ) method, you can take advantage of this method to track where the mouse is in the table.

public void selectAll( )

Select all cells (or all rows and all columns, if you prefer) in the table. This method is the opposite of the clearSelection( ) method. Whether this selection is reported as rows, columns, or cells depends on how the columnSelectionAllowed and rowSelectionAllowed properties are set.

15.1.7 The TableColumn Class

The TableColumn class is the starting point for building your columns. It supplies access to all the basic components of an individual column. This class should not be confused with the TableColumnModel interface. That model, discussed in the next section, dictates the form of a collection of table columns, which then makes up a full table.

15.1.7.1 Properties

The TableColumn class has the properties listed in Table 15-5.

Table 15-5. TableColumn properties

Property

Data type

get

is

set

Default value

cellEditor

TableCellEditor

·

 

·

null

cellRendererb

TableCellRenderer

·

 

·

null

headerRendererb

TableCellRenderer

·

 

·

null

headerValueb

Object

·

 

·

null

identifier

Object

·

 

·

null

maxWidth

int

·

 

·

Integer.MAX_VALUE

minWidth

int

·

 

·

15

modelIndex

int

·

 

·

0

propertyChangeListeners1.4

PropertyChangeListener[]

·

   

Empty array

resizable

boolean

·

 

·

true

widthb

int

·

 

·

75

bbound, 1.4since 1.4

The cellEditor , cellRenderer, and headerRenderer properties determine which components are used to draw (and possibly edit) cell values. The default value of null for these properties indicates that a default renderer or editor should be built and used. The headerValue property is accessible to the headerRenderer for drawing an appropriate header. The identifier property is used to identify a column uniquely. If an identifier is not specified, the getIdentifier( ) method returns the current headerValue. The minWidth and maxWidth properties determine the minimum and maximum width in pixels for the column. By setting these properties to the same value, you can create a fixed-width column. The current width of the column is stored in the width property. The modelIndex determines the index value used when rendering or editing the column to get the appropriate data values. It is normally set in the constructor and does not need to be modified after that. Relocating the column onscreen has no effect on the model index. The resizable property affects only the user's ability to manually resize columns you can programmatically resize a column at any time.

15.1.7.2 Constants

Four of the properties have descriptive constants that are used with property change events. These constants are listed in Table 15-6.

Table 15-6. TableColumn constants

Constant

Type

Description

CELL_RENDERER_PROPERTY

String

The property name of the cellRenderer property

COLUMN_WIDTH_PROPERTY

String

The property name of the columnWidth property

HEADER_RENDERER_PROPERTY

String

The property name of the headerRenderer property

HEADER_VALUE_PROPERTY

String

The property name of the headerValue property

15.1.7.3 Event

The only event generated by the TableColumn class is a property change event that is generated when any of the column's bound properties (cellRenderer, headerRenderer, headerValue, and width) are changed.

public void addPropertyChangeListener(PropertyChangeListener l)
public void removePropertyChangeListener(PropertyChangeListener l)

Add or remove a property change listener interested in receiving events from this column.

15.1.7.4 Constructors

The following constructors exist for building TableColumn objects:

public TableColumn( )

Create an empty column with the default property values.

public TableColumn(int modelIndex)

Create an empty column with the specified modelIndex.

public TableColumn(int modelIndex, int width)

Create an empty column with the specified modelIndex and width in pixels. The minWidth and maxWidth properties keep their default values.

public TableColumn(int modelIndex, int width, TableCellRenderer cellRenderer, TableCellEditor cellEditor)

Create an empty column with the specified modelIndex, width in pixels, cellRenderer, and cellEditor. The renderer or editor arguments can be null, in which case the appropriate default is used.

15.1.7.5 Another useful method

While the get/set methods for the properties constitute a majority of the TableColumn class, the following method does provide a bit of functionality:

public void sizeWidthToFit( )

Force the width of the column to match that of its header, even if it means modifying the minWidth or maxWidth properties.

15.1.8 The TableColumnModel Interface

A single column is not a very interesting table an interesting list, maybe, but not a table. To handle real tables (even ones with only one column), we need a model for storing several columns as a collection. The TableColumnModel interface provides that functionality in the Swing package. As you may have noticed from Figure 15-2, the JTable class has a column model in addition to a table model. While the table model provides the specific values for the cells in a column, the column model provides information such as the column margins and whether or not column selections are allowed.

The TableColumnModel interface manages column selections and column spacing. For managing selections, you have access to the usual selection properties, such as the number of selected columns and the selection model in place. For dealing with column spacing, you can control the column margins and view the total column width.

15.1.8.1 Properties

TableColumnModel has the properties listed in Table 15-7. The columnCount property returns the number of columns supported by this model. While this might seem like redundant information, given that the table model (discussed later in this chapter) knows how many columns it supports, the next chapter examines some column models that do not use all of the columns available in the table model. The columnMargin property dictates how much space should be left between columns. That spacing is included when calculating the value of the totalColumnWidth. You can turn column selection on or off with the columnSelectionAllowed property. If column selections are allowed, you can then use the selectionModel , selectedColumns, and selectedColumnCount properties to work with the selections. As with other selections, you can use the selectionModel to programmatically affect the selected columns if needed.

Table 15-7. TableColumnModel properties

Property

Data type

get

is

set

Default value

columni

TableColumn

·

     

columns

Enumeration

·

     

columnCount

int

·

     

columnMargin

int

·

 

·

 

columnSelectionAllowed

boolean

·

 

·

 

selectedColumnCount

int

·

     

selectedColumns

int[]

·

     

selectionModel

ListSelectionModel

·

 

·

 

totalColumnWidth

int

·

     

iindexed

The column and columns properties let you access the table's columns themselves. The index used as an argument to getColumn( ) refers to the column's index in the column model, which doesn't necessarily match the index of the column in the table model, or the order in which columns appear on the screen.

15.1.8.2 Event

Any class implementing the TableColumnModel interface has to support the ColumnModelEvent, which is generated when a column's view size, position, or extent size changes. The interface defines the standard addColumnModelListener( ) and removeColumnModelListener( ) methods, but the implementing class is responsible for the code that fires the events when columns are added, removed, or moved.

public void addColumnModelListener(TableColumnModelListener l)
public void removeColumnModelListener(TableColumnModelListener l)

Add or remove a listener interested in changes to this column model.

15.1.8.3 Column methods

The TableColumnModel interface defines several methods for working with the columns in the model:

public void addColumn(TableColumn column)

Append column to the current column model.

public int getColumnIndex(Object identifier)
public int getColumnIndexAtX(int xPixel)

Return the column model (screen) index of a column, either with a header matching identifier or at the specified xPixel location on the screen.

public void moveColumn(int index, int newIndex)

Move the column at index to newIndex. Other columns should be shifted as needed to accommodate the moved column. This visually relocates the column on the screen only. The table model does not change.

public void removeColumn(TableColumn column)

Delete column from the column model. Columns following the removed column are shifted one index to fill the gap.

15.1.9 The DefaultTableColumnModel Class

The DefaultTableColumnModel class implements the TableColumnModel interface and serves as the column model if you do not specify a model in the JTable constructor. It also works as a good starting point for creating your own column models. You inherit everything you need; just override the methods you want to change.

15.1.9.1 Properties

The DefaultTableColumnModel class inherits all of its properties from the TableColumnModel interface and supplies the default values shown in Table 15-8.

Table 15-8. DefaultTableColumnModel properties

Property

Data type

get

is

set

Default value

columni, o

TableColumn

·

     

columnso

Enumeration

·

     

columnCounto

int

·

   

0

columnMargino

int

·

 

·

1

columnSelectionAllowedo

boolean

·

 

·

false

selectedColumnCounto

int

·

   

0

selectedColumnso

int[]

·

   

null

selectionModelo

ListSelectionModel

·

 

·

DefaultListSelectionModel( )

totalColumnWidtho

int

·

   

0

iindexed, ooverridden

15.1.9.2 Events

The DefaultTableColumnModel supports the ColumnModelEvent events that are dictated by the TableColumnModel interface, but it includes several convenience methods beyond simply attaching listeners:

protected void fireColumnAdded(TableColumnModelEvent e)
protected void fireColumnMarginChanged( )
protected void fireColumnMoved(TableColumnModelEvent e)
protected void fireColumnRemoved(TableColumnModelEvent e)
protected void fireColumnSelectionChanged(ListSelectionEvent e)

These helper methods are used to fire events when columns are added, resized, relocated, removed, or selected. They also allow you to fire column-based events to create your own column model by extending this class.

public void addColumnModelListener(TableColumnModelListener x)
public void removeColumnModelListener(TableColumnModelListener x)

Add or remove a listener for TableColumnModelEvents fired by this model.

protected void propertyChange(PropertyChangeEvent e)
protected void valueChanged(ListSelectionEvent e)

The DefaultTableColumnModel listens to some of these events to keep the visual state of the table in sync. The COLUMN_WIDTH_PROPERTY change events (from one of the added TableColumn objects) cause the width cache for the table to be recalculated. The valueChanged( ) method listens for new column selections and fires a column selection changed event.

15.1.9.3 Constructor
public DefaultTableColumnModel( )

Set up a new DefaultTableColumnModel with the default values for properties listed in Table 15-8.

15.1.9.4 Other useful methods
public void addColumn(TableColumnColumn)
public int getColumnIndex(Object identifier)
public int getColumnIndexAtX(int xPixel)
public void moveColumn(int index, int newindex)
public void removeColumn(TableColumn column)

These methods provide straightforward implementation of the abstract methods required by the TableColumnModel interface.

15.1.10 The TableColumnModelEvent Class

Many of the events fired by the DefaultTableColumnModel class use this event class to encode the columns that were affected. Notice that these events describe something happening to a contiguous group of columns, unlike the selection events. There is no direct support for things like removing a discontiguous selection of columns. You must generate a different event for each contiguous range of columns that needs to be removed.

15.1.10.1 Event methods
public int getFromIndex( )
public int getToIndex( )

Use these methods to find the affected columns. If only a single column is affected, these methods return the same value.

15.1.11 The TableColumnModelListener Interface

If you want to listen to any of the column model events, you must implement the TableColumnModelListener interface and register as a listener for these events. Not surprisingly, the event-firing methods from the DefaultTableColumnModel class reflect the types of events this interface defines:

public void columnAdded(TableColumnModelEvent e)
public void columnMarginChanged(ChangeEvent e)
public void columnMoved(TableColumnModelEvent e)
public void columnRemoved(TableColumnModelEvent e)
public void columnSelectionChanged(ListSelectionEvent e)

Use these methods to react to changes in the column model. While you cannot add a ListSelectionListener directly to the column model if you care only about column selections, you can retrieve the selection model (using getSelectionModel( )) and attach a listener to that object.



Java Swing
Graphic Java 2: Mastering the Jfc, By Geary, 3Rd Edition, Volume 2: Swing
ISBN: 0130796670
EAN: 2147483647
Year: 2001
Pages: 289
Authors: David Geary

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net