Sei sulla pagina 1di 28

http://docs.oracle.com/javase/tutorial/uiswing/components/table.

html

How to Use Tables


With the JTable class you can display tables of data, optionally allowing the user to edit the data. JTable does not contain or cache data; it is simply a view of your data. Here is a picture of a typical table displayed within a scroll pane:

The rest of this section shows you how to accomplish some common table related tas!s. Here are the topics this section covers:

"reating a #imple Table $dding a Table to a "ontainer #etting and "hanging "olumn Widths %ser #elections "reating a Table &odel 'istening for (ata "hanges )iring (ata "hange *vents "oncepts: *ditors and +enderers %sing "ustom +enderers #pecifying Tool Tips for "ells #pecifying Tool Tips for "olumn Headers #orting and )iltering %sing a "ombo ,o- as an *ditor %sing .ther *ditors %sing an *ditor to /alidate %ser *ntered Te-t 0rinting *-amples that %se Tables

Creating a Simple Table


Try this:

1. "lic! the 'aunch button to run SimpleTableDemo using 2ava3 Web #tart 4download 2(5 6 or later7. .r, to compile and run the e-ample yourself, consult the e-ample inde-.

8. "lic! the cell that contains 9#nowboarding9. The entire first row is selected, indicating that you have selected 5athy #mith:s data. $ special highlight indicates that the 9#nowboarding9 cell is editable. ;enerally, you begin editing a te-t cell by double clic!ing it. <. 0osition the cursor over 9)irst =ame9. =ow press the mouse button and drag to the right. $s you can see, users can rearrange columns in tables. >. 0osition the cursor just to the right of a column header. =ow press the mouse button and drag to the right or left. The column changes si?e, and the other columns adjust to fill the remaining space. @. +esi?e the window containing the table so that it:s bigger than necessary to display the whole table. $ll the table cells become wider, e-panding to fill the e-tra hori?ontal space.

The table in SimpleTableDemo.java declares the column names in a #tring array:


String[] columnNames = {"First Name", " ast Name", "Sport", "! o" #ears", "$egetarian"%&

Ats data is initiali?ed and stored in a two dimensional .bject array:


'bject[][] (ata = { {")at*+", "Smit*", "Sno,boar(ing", ne, -nteger./0, ne, 1oolean."alse0%, {"Jo*n", "Doe", "2o,ing", ne, -nteger.30, ne, 1oolean.true0%, {"Sue", "1lac4", ")nitting", ne, -nteger.50, ne, 1oolean."alse0%, {"Jane", "6*ite", "Spee( rea(ing", ne, -nteger.570, ne, 1oolean.true0%, {"Joe", "1ro,n", "8ool", ne, -nteger.970, ne, 1oolean."alse0% %&

Then the Table is constructed using these data and column=ames:


JTable table = ne, JTable.(ata, columnNames0&

There are two JTable constructors that directly accept data 4SimpleTableDemo uses the first7:
JTable.'bject[][] ro,Data, 'bject[] columnNames0 JTable.$ector ro,Data, $ector columnNames0

The advantage of these constructors is that they are easy to use. However, these constructors also have disadvantages:

They automatically ma!e every cell editable. They treat all data types the same 4as strings7. )or e-ample, if a table column has 1oolean data, the table can display the data in a chec! bo-. However, if you use either of the two JTable constructors listed previously, your 1oolean data is displayed as a string. Bou can see this difference in the $egetarian column of the previous figure. They reCuire that you put all of the table:s data in an array or vector, which may not be appropriate for some data. )or e-ample, if you are instantiating a set of objects from a database, you might want to Cuery the objects directly for their values, rather than copying all their values into an array or vector.

Af you want to get around these restrictions, you need to implement your own table model, as described in "reating a Table &odel.

Adding a Table to a Container


Here is typical code for creating a scroll pane that serves as a container for a table:
JScroll8ane scroll8ane = ne, JScroll8ane.table0& table.setFills$ie,port:eig*t.true0&

The two lines in this snippet do the following:

The JScroll8ane constructor is invo!ed with an argument that refers to the table object. This creates a scroll pane as a container for the table; the table is automatically added to the container. JTable.setFills$ie,port:eig*t is invo!ed to set the "ills$ie,port:eig*t property. When this property is true the table uses the entire height of the container, even if the table doesn:t have enough rows to use the whole vertical space. This ma!es it easier to use the table as a drag and drop target.

The scroll pane automatically places the table header at the top of the viewport. The column names remain visible at the top of the viewing area when the table data is scrolled. Af you are using a table without a scroll pane, then you must get the table header component and place it yourself. )or e-ample:

container.set a+out.ne, 1or(er a+out.00& container.a((.table.getTable:ea(er.0, 1or(er a+out.8;<=>ST;2T0& container.a((.table, 1or(er a+out.?=NT=20&

Setting and Changing Column Widths


,y default, all columns in a table start out with eCual width, and the columns automatically fill the entire width of the table. When the table becomes wider or narrower 4which might happen when the user resi?es the window containing the table7, all the column widths change appropriately. When the user resi?es a column by dragging its right border, then either other columns must change si?e, or the table:s si?e must change. ,y default, the table:s si?e remains the same, and all columns to the right of the drag point resi?e to accommodate space added to or removed from the column to the left of the drag point. To customi?e initial column widths, you can invo!e set8re"erre(6i(t* on each of your table:s columns. This sets both the preferred widths of the columns and their appro-imate relative widths. )or e-ample, adding the following code to SimpleTableDemo ma!es its third column bigger than the other columns:
Table?olumn column = null& "or .int i = 7& i @ /& iAA0 { column = table.get?olumnBo(el.0.get?olumn.i0& i" .i == 50 { column.set8re"erre(6i(t*.9770& CCt*ir( column is bigger % else { column.set8re"erre(6i(t*./70& % %

$s the preceding code shows, each column in a table is represented by a Table?olumn object. Table?olumn supplies getter and setter methods for the minimum, preferred, and ma-imum widths of a column, as well as a method for getting the current width. )or an e-ample of setting cell widths based on an appro-imation of the space needed to draw the cells: contents, see the init?olumnSiDes method in Table2en(erDemo.java. When the user e-plicitly resi?es columns, the columns: preferred widths are set such that the user specified si?es become the columns: new current widths. However, when table itself is resi?ed D typically because the window has resi?ed D; the columns: preferred widths do not change. Anstead, the e-isting preferred widths are used to calculate new column widths to fill the available space. Bou can change a table:s resi?e behavior by invo!ing set;uto2esiDeBo(e.

User Selections

An its default configuration, a table supports a selection that consists of one or more rows. The user can select a contiguous range of rows or an arbitrary set of rows. The last cell that the user indicated gets a special indication; in the &etal loo! and feel, the cell is outlined. This cell is !nown as the lead selection; it is sometimes called 9the cell with the focus9 or 9the current cell9. The user uses the mouse and/or !eyboard to ma!e selections, as described in the following table: Operation #elect single row. *-tend contiguous selection. $dd row to selection/toggle row selection. Mouse Action "lic!. Keyboard Action %p $rrow or (own $rrow.

#hift "lic! or (rag over #hift %p $rrow or #hift (own $rrow. rows. &ove lead selection with "ontrol %p $rrow or "ontrol (own $rrow, then use #pace ,ar to "ontrol "lic! add to selection or "ontrol #pace ,ar to toggle row selection.

To see how selections wor!, clic! the 'aunch button to run TableSelectionDemo using 2ava3 Web #tart 4download 2(5 6 or later7. .r, to compile and run the e-ample yourself, consult the e-ample inde-.

This e-ample program presents the familiar table, and allows the user to manipulate certain 2Table options. There is also a te-t pane that logs selection events. An the screenshot below, a user has run the program, clic!ed in the first row, then control clic!ed in the third row. =otice the outline around the last cell clic!ed; this is how the &etal loo! and feel highlights the lead selection.

%nder 9#election &ode9 there are a set of radio buttons. "lic! the one labelled 9#ingle #election9. =ow you can only select one row at a time. Af you clic! on the 9#ingle Anterval #election9 radio button, you can select a set of rows that must be contiguous. $ll of the radio buttons under 9#election &ode9 invo!e JTable.setSelectionBo(e. This method ta!es a single argument, which must be one of the following constants defined in javaE.s,ing. istSelectionBo(el: BF T-8 =>-NT=2$; >S= =?T-'N, S-N< =>-NT=2$; >S= =?T-'N, and S-N< =>S= =?T-'N. +eturning to TableSelectionDemo, notice the three option chec!bo-es under 9#election .ptions.9 *ach of chec!bo- controls the state of a boolean bound variable defined by JTable:

9+ow #election9 controls ro,Selection;llo,e( which has setter method set2o,Selection;llo,e( and getter method get2o,Selection;llo,e(. When this bound property is true 4and the columnSelection;llo,e( property is "alse7, the user can select by row. 9"olumn #election9 controls columnSelection;llo,e( which has setter method set?olumnSelection;llo,e( and getter method get?olumnSelection;llo,e(. When this bound property is true 4and the ro,Selection;llo,e( bound property is "alse7, the user can select by column. 9"ell #election9 controls cellSelection=nable(, which has setter method set?ellSelection=nable( and getter method get?ellSelection=nable(.

When this bound property is true, the user can select a single cell or rectangular bloc! of cells. OT!: JTable uses a very simple concept of selection, managed as an intersection of rows and columns. At was not designed to handle fully independent cell selections. Af you clear all three chec! bo-es 4setting all three bound properties to "alse7, there is no selection; only the lead selection is shown. Bou may notice that the 9"ell #election9 chec!bo- is disabled in multiple interval selection mode. This is because cell selection is not supported in this mode in the demo. Bou can specify selection by cell in multiple interval selection mode, but the result is a table that does not produce useful selections. Bou may also notice that changing any of the three selection options can affect the others. This is because allowing both row selection and column selection is e-actly the same as enabling cell selection. JTable automatically updates the three bound variables as necessary to !eep them consistent. OT!: #etting cellSelection=nable( to a value has the side effect of also setting both ro,Selection=nable( and columnSelection=nable( to that value. #etting both ro,Selection=nable( and columnSelection=nable( to a value has the side effect of also setting cellSelection=nable( to that value. #etting ro,Selection=nable( and columnSelection=nable( to different values has the side effect of also setting cellSelection=nable( to "alse. To retrieve the current selection, use JTable.getSelecte(2o,s which returns an array of row inde-es, and JTable.getSelecte(?olumns which returns an array of column inde-es. To retrieve the coordinates of the lead selection, refer to the selection models for the table itself and for the table:s column model. The following code formats a string containing the row and column of the lead selection:
String."ormat." ea( SelectionG H(, H(. ", table.getSelectionBo(el.0.get ea(Selection-n(eE.0, table.get?olumnBo(el.0.getSelectionBo(el.0.get ea(Selection-n(eE.00&

%ser selections generate a number of events. )or information on these, refer to How to Write a 'ist #election 'istener in the Writing *vent 'isteners lesson. OT!: #election data actually describes selected cells in the 9view9 4table data as it appears after any sorting or filtering7 rather than in the table model. This distinction does not matter unless your viewed data has been rearranged by sorting, filtering, or user manipulation of columns. An that case, you must convert selection coordinates using the conversion methods described in #orting and )iltering.

Creating a Table Model

*very table object uses a table model object to manage the actual table data. $ table model object must implement the TableBo(el interface. Af the programmer does not provide a table model object, JTable automatically creates an instance of De"aultTableBo(el. This relationship is illustrated below.

The JTable constructor used by SimpleTableDemo creates its table model with code li!e this:
ne, ;bstractTableBo(el.0 { public String get?olumnName.int col0 { return columnNames[col].toString.0& % public int get2o,?ount.0 { return ro,Data.lengt*& % public int get?olumn?ount.0 { return columnNames.lengt*& % public 'bject get$alue;t.int ro,, int col0 { return ro,Data[ro,][col]& % public boolean is?ell=(itable.int ro,, int col0 { return true& % public voi( set$alue;t.'bject value, int ro,, int col0 { ro,Data[ro,][col] = value& "ireTable?ellFp(ate(.ro,, col0& % %

$s the preceding code shows, implementing a table model can be simple. ;enerally, you implement your table model in a subclass of the ;bstractTableBo(el class. Bour model might hold its data in an array, vector, or hash map, or it might get the data from an outside source such as a database. At might even generate the data at e-ecution time. This table is different from the SimpleTableDemo table in the following ways:
TableDemo:s

custom table model, even though it is simple, can easily determine the data:s type, helping the JTable display the data in the best format. SimpleTableDemo:s automatically created table model, on the other hand, does not !now that the " o# $ears column contains numbers 4which should generally be right aligned and have a particular format7. At also does not !now that the $egetarian column contains boolean values, which can be represented by chec! bo-es.

The custom table model implemented in TableDemo does not let you edit the name columns; it does, however, let you edit the other columns. An SimpleTableDemo, all cells are editable.

#ee below the code ta!en from TableDemo.java that is different from the SimpleTableDemo.java. ,old font indicates the code that ma!es this table:s model different from the table model defined automatically for SimpleTableDemo.
public TableDemo.0 { ... JTable table = ne, JTable.ne, B+TableBo(el.00& ... % class B+TableBo(el eEten(s ;bstractTableBo(el { private String[] columnNames = ...//same as before... private 'bject[][] (ata = ...//same as before... public int get?olumn?ount.0 { return columnNames.lengt*& % public int get2o,?ount.0 { return (ata.lengt*& % public String get?olumnName.int col0 { return columnNames[col]& % public 'bject get$alue;t.int ro,, int col0 { return (ata[ro,][col]& % public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } CI I DonJt nee( to implement t*is met*o( unless +our tableJs I e(itable. IC public boolean is?ell=(itable.int ro,, int col0 { CCNote t*at t*e (ataCcell a((ress is constant, CCno matter ,*ere t*e cell appears onscreen. if (col < 2) { return false; } else { return true; } % CI I DonJt nee( to implement t*is met*o( unless +our tableJs I (ata can c*ange. IC public voi( set$alue;t.'bject value, int ro,, int col0 {

% ...

(ata[ro,][col] = value& "ireTable?ellFp(ate(.ro,, col0&

%istening #or &ata Changes


$ table model can have a set of listeners that are notified whenever the table data changes. 'isteners are instances of TableBo(el istener. An the following e-ample code, SimpleTableDemo is e-tended to include such a listener. =ew code is in bold.
import ja a!.s"ing.e ent.#; import ja a!.s"ing.table.$able%o&el; public class SimpleTableDemo ... implements $able%o&el'istener { ... public SimpleTableDemo.0 { ... table.get%o&el().a&&$able%o&el'istener(t(is); ... % public oi& tableC(ange&($able%o&el) ent e) { int ro" * e.get+irst,o"(); int column * e.getColumn(); $able%o&el mo&el * ($able%o&el)e.get-ource(); -tring column.ame * mo&el.getColumn.ame(column); /bject &ata * mo&el.getValueAt(ro", column); % ... ...// Do something with the data...

'iring &ata Change !(ents


An order to fire data change events the table model must !now how to construct a TableBo(el=vent object. This can be a comple- procedure, but is already implemented in De"aultTableBo(el. Bou can either allow JTable to use its default instance of De"aultTableBo(el, or create your own custom subclass of De"aultTableBo(el. Af De"aultTableBo(el is not a suitable base class for your custom table model class, consider subclassing ;bstractTableBo(el. This class implements a simple framewor! for constructing TableBo(el=vent objects. Bour custom class simply needs to invo!e one the following ;bstractTableBo(el methods each time table data is changed by an e-ternal source. Method
"ireTable?ellFp(ate(

Change %pdate of specified cell.

"ireTable2o,sFp(ate( "ireTableData?*ange( "ireTable2o,s-nserte( "ireTable2o,sDelete( "ireTableStructure?*ange(

%pdate of specified rows %pdate of entire table 4data only7. =ew rows inserted. *-isting rows (eleted Anvalidate entire table, both data and structure.

Concepts: !ditors and )enderers


,efore you go on to the ne-t few tas!s, you need to understand how tables draw their cells. Bou might e-pect each cell in a table to be a component. However, for performance reasons, #wing tables are implemented differently. Anstead, a single cell renderer is generally used to draw all of the cells that contain the same type of data. Bou can thin! of the renderer as a configurable in! 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 ta!es over the cell, controlling the cell:s editing behavior. )or e-ample, each cell in the " o# $ears column in TableDemo contains Number data D specifically, an -nteger object. ,y default, the cell renderer for a Number containing column uses a single J abel instance to draw the appropriate numbers, right aligned, on the column:s cells. Af the user begins editing one of the cells, the default cell editor uses a right aligned JTeEtFiel( to control the cell editing. To choose the renderer that displays the cells in a column, a table first determines whether you specified a renderer for that particular column. Af you did not, then the table invo!es the table model:s get?olumn?lass method, which gets the data type of the column:s cells. =e-t, the table compares the column:s data type with a list of data types for which cell renderers are registered. This list is initiali?ed by the table, but you can add to it or change it. "urrently, tables put the following types of data in the list:
1oolean D rendered with a chec! bo-. Number D rendered by a right aligned label. Double, Float D same as Number, but the object to te-t translation is performed by a NumberFormat instance 4using the default number format

for

the current locale7. Date D rendered by a label, with the object to te-t translation performed by a DateFormat instance 4using a short style for the date and time7. -mage-con, -con D rendered by a centered label. 'bject D rendered by a label that displays the object:s string value.

"ell editors are chosen using a similar algorithm.

+emember that if you let a table create its own model, it uses 'bject as the type of every column. To specify more precise column types, the table model must define the get?olumn?lass method appropriately, as demonstrated by TableDemo.java. 5eep in mind that although renderers determine how each cell or column header loo!s and can specify its tool tip te-t, a renderer does not handle events. Af you need to pic! up the events that ta!e place inside a table, the techniCue you use varies by the sort of event you are interested in: Situation To detect events from a cell that is being edited... How to *et !(ents %se the cell editor 4or register a listener on the cell editor7.

To detect row/column/cell %se a selection listener as described in (etecting %ser selections and deselections... #elections. To detect mouse events on a +egister the appropriate type of mouse listener on the column header... table:s JTable:ea(er object. 4#ee TableSorter.java for an e-ample.7 To detect other events... +egister the appropriate listener on the JTable object.

The ne-t few sections tell you how to customi?e display and editing by specifying renderers and editors. Bou can specify cell renderers and editors either by column or by data type.

Using Custom )enderers


This section tells you how to create and specify a cell renderer. Bou can set a type specific cell renderer using the JTable method setDe"ault2en(erer. To specify that cells in a particular column should use a renderer, you use the Table?olumn method set?ell2en(erer. Bou can even specify a cell specific renderer by creating a JTable subclass. At is easy to customi?e the te-t or image rendered by the default renderer, De"aultTable?ell2en(erer. Bou just create a subclass and implement the set$alue method so that it invo!es setTeEt or set-con with the appropriate string or image. )or e-ample, here is how the default date renderer is implemented:
static class Date2en(erer eEten(s De"aultTable?ell2en(erer { DateFormat "ormatter& public Date2en(erer.0 { super.0& % public voi( set$alue.'bject value0 { i" ."ormatter==null0 { "ormatter = DateFormat.getDate-nstance.0& % setTeEt..value == null0 K "" G "ormatter."ormat.value00& %

Af e-tending De"aultTable?ell2en(erer is insufficient, you can build a renderer using another superclass. The easiest way is to create a subclass of an e-isting component, ma!ing your subclass implement the Table?ell2en(erer interface. Table?ell2en(erer reCuires just one method: getTable?ell2en(erer?omponent. Bour implementation of this method should set up the rendering component to reflect the passed in state, and then return the component. An the snapshot of TableDialog=(itDemo, the renderer used for 'a(orite Color cells is a subclass of J abel called ?olor2en(erer. Here are e-cerpts from ?olor2en(erer.java that show how it is implemented.
public class ?olor2en(erer eEten(s J abel implements Table?ell2en(erer { ... public ?olor2en(erer.boolean is1or(ere(0 { t*is.is1or(ere( = is1or(ere(& set'paLue.true0& CCBFST (o t*is "or bac4groun( to s*o, up. % public ?omponent getTable?ell2en(erer?omponent. JTable table, 'bject color, boolean isSelecte(, boolean *asFocus, int ro,, int column0 { ?olor ne,?olor = .?olor0color& set1ac4groun(.ne,?olor0& i" .is1or(ere(0 { i" .isSelecte(0 { ... CCselecte(1or(er is a soli( bor(er in t*e color CCtable.getSelection1ac4groun(.0. set1or(er.selecte(1or(er0& % else { ... CCunselecte(1or(er is a soli( bor(er in t*e color CCtable.get1ac4groun(.0. set1or(er.unselecte(1or(er0& % % setToolTipTeEt....0& //Discussed in the following section return t*is&

% %

Here is the code from TableDialog=(itDemo.java that registers a ?olor2en(erer instance as the default renderer for all ?olor data:
table.setDe"ault2en(erer.?olor.class, ne, ?olor2en(erer.true00&

To specify a cell specific renderer, you need to define a JTable subclass that overrides the get?ell2en(erer method. )or e-ample, the following code ma!es the first cell in the first column of the table use a custom renderer:
Table?ell2en(erer ,eir(2en(erer = ne, 6eir(2en(erer.0&

table = ne, JTable....0 { public Table?ell2en(erer get?ell2en(erer.int ro,, int column0 { i" ..ro, == 70 MM .column == 700 { return ,eir(2en(erer& % CC else... return super.get?ell2en(erer.ro,, column0& % %&

Speci#ying Tool Tips #or Cells


,y default, the tool tip te-t displayed for a table cell is determined by the cell:s renderer. However, sometimes it can be simpler to specify tool tip te-t by overriding JTable:s implementation of the getToolTipTeEt.Bouse=vent0 method. This section shows you how to use both techniCues. To add a tool tip to a cell using its renderer, you first need to get or create the cell renderer. Then, after ma!ing sure the rendering component is a J?omponent, invo!e the setToolTipTeEt method on it. $n e-ample of setting tool tips for cells is in Table2en(erDemo. "lic! the 'aunch button to run it using 2ava3 Web #tart 4download 2(5 6 or later7. .r, to compile and run the e-ample yourself, consult the e-ample inde-.

The source code is in Table2en(erDemo.java. At adds tool tips to the cells of the Sport column with the following code:
CCSet up tool tips "or t*e sport cells. De"aultTable?ell2en(erer ren(erer = ne, De"aultTable?ell2en(erer.0& ren&erer.set$ool$ip$e!t(0Clic1 for combo bo!0); sport?olumn.set?ell2en(erer.ren(erer0&

$lthough the tool tip te-t in the previous e-ample is static, you can also implement tool tips whose te-t changes depending on the state of the cell or program. Here are a couple ways to do so:

$dd a bit of code to the renderer:s implementation of the getTable?ell2en(erer?omponent method. .verride the JTable method getToolTipTeEt.Bouse=vent0.

$n e-ample of adding code to a cell renderer is in TableDialog=(itDemo. "lic! the 'aunch button to run it using 2ava3 Web #tart 4download 2(5 6 or later7. .r, to compile and run the e-ample yourself, consult the e-ample inde-.

TableDialog=(itDemo uses a renderer for colors, implemented in ?olor2en(erer.java, that sets the tool tip te-t using the boldface

code in the

following snippet:
public class ?olor2en(erer eEten(s J abel implements Table?ell2en(erer { ... public ?omponent getTable?ell2en(erer?omponent. JTable table, 'bject color, boolean isSelecte(, boolean *asFocus, int ro,, int column0 { ?olor ne,?olor = .?olor0color& ... set$ool$ip$e!t(0,23 alue4 0 5 ne"Color.get,e&() 5 0, 0 5 ne"Color.get2reen() 5 0, 0 5 ne"Color.get3lue()); return t*is& % %

Here is an e-ample of what the tool tip loo!s li!e:

Bou can specify tool tip te-t by overriding JTable:s getToolTipTeEt.Bouse=vent0 method. The program TableToolTipsDemo shows how. "lic! the 'aunch button to run it using 2ava3 Web #tart 4download 2(5 6 or later7. .r, to compile and run the e-ample yourself, consult the e-ample inde-.

The cells with tool tips are in the Sport and +egetarian columns. Here is a picture of its tool tip:

Here is the code from TableToolTipsDemo.java that implements tool tips for cells in the Sport and +egetarian columns:
JTable table = ne, JTable.ne, B+TableBo(el.00 {

CC-mplement table cell tool tips. public String getToolTipTeEt.Bouse=vent e0 { String tip = null& java.a,t.8oint p = e.get8oint.0& int ro,-n(eE = ro,;t8oint.p0& int col-n(eE = column;t8oint.p0& int real?olumn-n(eE = convert?olumn-n(eEToBo(el.col-n(eE0& i" .real?olumn-n(eE == 50 { CCSport column tip = "T*is personJs "avorite sport to " A "participate in isG " A get$alue;t.ro,-n(eE, col-n(eE0& % else i" .real?olumn-n(eE == N0 { CC$eggie column TableBo(el mo(el = getBo(el.0& String "irstName = .String0mo(el.get$alue;t.ro,-n(eE,70& String lastName = .String0mo(el.get$alue;t.ro,-n(eE,90& 1oolean veggie = .1oolean0mo(el.get$alue;t.ro,-n(eE,N0& i" .1oolean.T2F=.eLuals.veggie00 { tip = "irstName A " " A lastName A " is a vegetarian"& % else { tip = "irstName A " " A lastName A " is not a vegetarian"& % % else { CCanot*er column CC#ou can omit t*is part i" +ou 4no, +ou (onJt CC*ave an+ ren(erers t*at suppl+ t*eir o,n tool CCtips. tip = super.getToolTipTeEt.e0& % return tip& % ... %

The code is fairly straightforward, e-cept perhaps for the call to convert?olumn-n(eEToBo(el. That call is necessary because if the user moves the columns around, the view:s inde- for the column will not match the model:s inde- for the column. )or e-ample, the user might drag the +egetarian column 4which the model considers to be at inde- >7 so it is displayed as the first column D at view inde- E. #ince prepare2en(erer provides the view inde-, you need to translate the view inde- to a model inde- so you can be sure the intended column has been selected.

Speci#ying Tool Tips #or Column Headers


Bou can add a tool tip to a column header by setting the tool tip te-t for the table:s JTable:ea(er. .ften, different column headers reCuire different tool tip te-t. Bou can change the te-t by overriding the table header:s getToolTipTeEt method. $lternately, you can invo!e Table?olumn.set:ea(er2en(erer to provide a custom renderer for the header.

$n e-ample of using the same tool tip te-t for all column headers is in TableSorterDemo.java. Here is how it sets the tool tip te-t:
table.getTable:ea(er.0.setToolTipTeEt. "?lic4 to sort& S*i"tO?lic4 to sort in reverse or(er"0&

has an e-ample of implementing column header tool tips that vary by column. Af you run TableToolTipsDemo 4clic! the 'aunch button7 using 2ava3 Web #tart 4download 2(5 6 or later7. .r, to compile and run the e-ample yourself, consult the e-ample inde-.
TableToolTipsDemo.java

Bou will see the tool tips when you mouse over any column header e-cept for the first two. =o tool tips were suppled for the name columns since they seemed self e-planatory. Here is a picture of one of the column header tool tips:

The following code implements the tool tips. ,asically, it creates a subclass of JTable:ea(er that overrides the getToolTipTeEt.Bouse=vent0 method so that it returns the te-t for the current column. To associate the revised table header with the table, the JTable method createDe"aultTable:ea(er is overridden so that it returns an instance of the JTable:ea(er subclass.
protecte( String[] columnToolTips = { null, CC "First Name" assume( obvious null, CC " ast Name" assume( obvious "T*e personJs "avorite sport to participate in", "T*e number o" +ears t*e person *as pla+e( t*e sport", "-" c*ec4e(, t*e person eats no meat"%& ... JTable table = ne, JTable.ne, B+TableBo(el.00 { ... CC-mplement table *ea(er tool tips. protecte( JTable:ea(er createDe"aultTable:ea(er.0 { return ne, JTable:ea(er.columnBo(el0 { public String getToolTipTeEt.Bouse=vent e0 { String tip = null& java.a,t.8oint p = e.get8oint.0& int in(eE = columnBo(el.get?olumn-n(eE;tP.p.E0& int real-n(eE = columnBo(el.get?olumn.in(eE0.getBo(el-n(eE.0&

return columnToolTips[real-n(eE]& %& %& % %

Sorting and 'iltering


Table sorting and filtering is managed by a sorter object. The easiest way to provide a sorter object is to set auto?reate2o,Sorter bound property to true:
JTable table = ne, JTable.0& table.set;uto?reate2o,Sorter.true0&

This action defines a row sorter that is an instance of javaE.s,ing.table.Table2o,Sorter. This provides a table that does a simple locale specific sort when the user clic!s on a column header. This is demonstrated in TableSortDemo.java, as seen in this screen shot:

To have more control over sorting, you can construct an instance of Table2o,Sorter and specify that it is the sorter object for your table.
Table2o,Sorter@TableBo(elQ sorter = ne, Table2o,Sorter@TableBo(elQ.table.getBo(el.00& table.set2o,Sorter.sorter0&

uses java.util.?omparator objects to sort its rows. $ class that implements this interface must provide a method called compare that defines how any two objects are compared for the purpose of sorting. )or e-ample, the following code creates a ?omparator that sorts a set of strings by the last word in each string:
Table2o,Sorter ?omparator@StringQ comparator = ne, ?omparator@StringQ.0 { public int compare.String s9, String s50 { String[] strings9 = s9.split."RRs"0& String[] strings5 = s5.split."RRs"0& return strings9[strings9.lengt* O 9] .compareTo.strings5[strings5.lengt* O 9]0& % %&

This e-ample is fairly simplistic; more typically, a ?omparator implementation is a subclass of java.teEt.?ollator. Bou can define your own subclass, use the

factory methods in ?ollator to obtain a ?omparator for a specific locale, or use java.teEt.2ule1ase(?ollator. To determine which ?omparator to use for a column, Table2o,Sorter attempts to apply each of the following rules in turn. +ules are followed in the order listed below; the first rule that provides the sorter with a ?omparator is used, and the remainining rules ignored. 1. Af a comparator has been specified by invo!ing set?omparator, use that comparator. 8. Af the table model reports that the column data consists of strings 4TableBo(el.get?olumn?lass returns String.class for that column7, use a comparator that sorts the strings based on the current locale. <. Af the column class returned by TableBo(el.get?olumn?lass implements ?omparable, use a comparator that sorts the strings based on the values returned by ?omparable.compareTo. >. Af a string convertor has been specified for the table by invo!ing setString?onverter, use a comparator that sorts the resulting string representations based on the current locale. @. Af none of the previous rules apply, use a comparator that invo!es toString on the column data and sorts the resulting strings based on the current locale. )or more sophisticated !inds of sorting, subclass Table2o,Sorter or its parent class javaE.s,ing.De"ault2o,Sorter. To specify the sort order and sort precedence for columns, invo!e setSort)e+s. Here is an e-ample that sorts the table used in the e-amples by the first two columns. The precedence of the columns in the sort is indicated by the order of the sort !eys in the sort !ey list. An this case, the second column has the first sort !ey, so they rows are sorted by first name, then last name.
ist @2o,Sorter.Sort)e+Q sort)e+s = ne, ;rra+ ist@2o,Sorter.Sort)e+Q.0& sort)e+s.a((.ne, 2o,Sorter.Sort)e+.9, Sort'r(er.;S?=ND-N<00& sort)e+s.a((.ne, 2o,Sorter.Sort)e+.7, Sort'r(er.;S?=ND-N<00& sorter.setSort)e+s.sort)e+s0&

An addition to reordering the results, a table sorter can also specify which rows will be displayed. This is !nown as filtering. Table2o,Sorter implements filtering using javaE.s,ing.2o,Filter objects. 2o,Filter implements several factory methods that create common !inds of filters. )or e-ample, regeEFilter returns a 2o,Filter that filters based on a regular e-pression. An the following e-ample code, you e-plicitly create a sorter object so you can later use it to specify a filter:
B+TableBo(el mo(el = ne, B+TableBo(el.0& sorter = ne, Table2o,Sorter@B+TableBo(elQ.mo(el0& table = ne, JTable.mo(el0&

table.set2o,Sorter.sorter0&

Then you filter based on the current value of a te-t field:


private voi( ne,Filter.0 { 2o,Filter@B+TableBo(el, 'bjectQ r" = null& CC-" current eEpression (oesnJt parse, (onJt up(ate. tr+ { r" = 2o,Filter.regeEFilter."ilterTeEt.getTeEt.0, 70& % catc* .java.util.regeE.8atternS+ntaE=Eception e0 { return& % sorter.set2o,Filter.r"0& %

An a subseCuent e-ample, ne,Filter.0 is invo!ed every time the te-t field changes. When the user enters complicated regular e-pressions, the tr+...catc* prevents the synta- e-ception from interfering with input. When a table uses a sorter, the data the users sees may be in a different order than that specified by the data model, and may not include all rows specified by the data model. The data the user actually sees is !nown as the view, and has its own set of coordinates. JTable provides methods that convert from model coordinates to view coordinates D convert?olumn-n(eETo$ie, and convert2o,-n(eETo$ie, D and that convert from view coordinates to model coordinates D convert?olumn-n(eEToBo(el and convert2o,-n(eEToBo(el. OT!: When using a sorter, always remember to translate cell coordinates. The following e-ample brings together the ideas discussed in this section. TableFilterDemo.java adds a small number of changes to TableDemo. These include the code snippets earlier in this section, which provide a sorter for the main table, and use a te-t field to supply the filtering regular e-pression. The following screen shot shows TableFilterDemo before any sorting or filtering has been done. =otice that row < in the model is still the same as row < in the view:

Af the user clic!s twice on the second column, the fourth row becomes the first row D but only in the view:

$s previously noted, the te-t the user enters in the 9)ilter Te-t9 te-t field defines a filter that determines which rows are shown. $s with sorting, filtering can cause view coordinates to diverge from model coordinates:

Here is the code that updates the status field to reflect the current selection:
table.getSelectionBo(el.0.a(( istSelection istener. ne, istSelection istener.0 { public voi( value?*ange(. istSelection=vent event0 { int vie,2o, = table.getSelecte(2o,.0& i" .vie,2o, @ 70 { CCSelection got "iltere( a,a+. statusTeEt.setTeEt.""0& % else { int mo(el2o, = table.convert2o,-n(eEToBo(el.vie,2o,0& statusTeEt.setTeEt. String."ormat."Selecte( 2o, in vie,G H(. " A "Selecte( 2o, in mo(elG H(.", vie,2o,, mo(el2o,00& % % % 0&

Using a Combo ,o- as an !ditor


#etting up a combo bo- as an editor is simple, as the following e-ample shows. The bold line of code sets up the combo bo- as the editor for a specific column.

Table?olumn sport?olumn = table.get?olumnBo(el.0.get?olumn.50& ... J?ombo1oE combo1oE = ne, J?ombo1oE.0& combo1oE.a((-tem."Sno,boar(ing"0& combo1oE.a((-tem."2o,ing"0& combo1oE.a((-tem."?*asing to((lers"0& combo1oE.a((-tem."Spee( rea(ing"0& combo1oE.a((-tem."Teac*ing *ig* sc*ool"0& combo1oE.a((-tem."None"0& sportColumn.setCell)&itor(ne" 6efaultCell)&itor(combo3o!));

Here is a picture of the combo bo- editor in use:

The preceding code is from Table2en(erDemo.java. Bou can run Table2en(erDemo 4clic! the 'aunch button7 using 2ava3 Web #tart 4download 2(5 6 or later7. .r, to compile and run the e-ample yourself, consult the e-ample inde-.

Using Other !ditors


Whether you are setting the editor for a single column of cells 4using the Table?olumn set?ell=(itor method7 or for a specific type of data 4using the JTable setDe"ault=(itor method7, you specify the editor using an argument that adheres to the Table?ell=(itor interface. )ortunately, the De"ault?ell=(itor class implements this interface and provides constructors to let you specify an editing component that is a JTeEtFiel(, J?*ec41oE, or J?ombo1oE. %sually you do not have to e-plicitly specify a chec! bo- as an editor, since columns with 1oolean data automatically use a chec! bo- renderer and editor. What if you want to specify an editor other than a te-t field, chec! bo-, or combo bo-F $s De"ault?ell=(itor does not support other types of components, you must do a little more wor!. Bou need to create a class that implements the Table?ell=(itor interface. The ;bstract?ell=(itor class is a good superclass to use. At implements Table?ell=(itor:s superinterface, ?ell=(itor, saving you the trouble of implementing the event firing code necessary for cell editors.

Bour cell editor class needs to define at least two methods D get?ell=(itor$alue and getTable?ell=(itor?omponent. The get?ell=(itor$alue method, reCuired by ?ell=(itor, returns the cell:s current value. The getTable?ell=(itor?omponent method, reCuired by Table?ell=(itor, should configure and return the component that you want to use as the editor. 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 'a(orite Color column, a button 4the true cell editor7 appears and brings up the dialog, with which the user can choose a different color.

Bou can run TableDialog=(itDemo 4clic! the 'aunch button7 using 2ava3 Web #tart 4download 2(5 6 or later7. .r, to compile and run the e-ample yourself, consult the e-ample inde-.

Here is the code, ta!en from ?olor=(itor.java, that implements the cell editor.
public class ?olor=(itor eEten(s ;bstract?ell=(itor implements Table?ell=(itor, ;ction istener { ?olor current?olor& J1utton button& J?olor?*ooser color?*ooser&

JDialog (ialog& protecte( static "inal String =D-T = "e(it"& public ?olor=(itor.0 { button = ne, J1utton.0& button.set;ction?omman(.=D-T0& button.a((;ction istener.t*is0& button.set1or(er8ainte(."alse0& CCSet up t*e (ialog t*at t*e button brings up. color?*ooser = ne, J?olor?*ooser.0& (ialog = J?olor?*ooser.createDialog.button, "8ic4 a ?olor", true, CCmo(al color?*ooser, t*is, CC') button *an(ler null0& CCno ?;N?= button *an(ler % public voi( action8er"orme(.;ction=vent e0 { i" .=D-T.eLuals.e.get;ction?omman(.000 { CCT*e user *as clic4e( t*e cell, so CCbring up t*e (ialog. button.set1ac4groun(.current?olor0& color?*ooser.set?olor.current?olor0& (ialog.set$isible.true0& "ire=(itingStoppe(.0& CCBa4e t*e ren(erer reappear. % else { CCFser presse( (ialogJs "')" button. current?olor = color?*ooser.get?olor.0& % % CC-mplement t*e one ?ell=(itor met*o( t*at ;bstract?ell=(itor (oesnJt. public 'bject get?ell=(itor$alue.0 { return current?olor& % CC-mplement t*e one met*o( (e"ine( b+ Table?ell=(itor. public ?omponent getTable?ell=(itor?omponent.JTable table, 'bject value, boolean isSelecte(, int ro,, int column0 { current?olor = .?olor0value& return button& %

$s you can see, the code is pretty simple. The only part that is a bit tric!y is the call to "ire=(itingStoppe( at the end of the editor button:s action handler. Without this call, the editor would remain active, even though the modal dialog is no longer visible. The call to "ire=(itingStoppe( lets the table !now that it can deactivate the editor, letting the cell be handled by the renderer again.

Using an !ditor to +alidate User.!ntered Te-t


Af a cell:s default editor allows te-t entry, you get some error chec!ing for free if the cell:s type is specified as something other than String or 'bject. The error chec!ing is a side effect of converting the entered te-t into an object of the proper type. The automatic chec!ing of user entered strings occurs when the default editor attempts to create a new instance of the class associated with the cell:s column. The default editor creates this instance using a constructor that ta!es a String as an argument. )or e-ample, in a column whose cells have type -nteger, when the user types in 918<9 the default editor creates the corresponding -nteger using code eCuivalent to ne, -nteger."953"0. Af the constructor throws an e-ception, the cell:s outline turns red and refuses to let focus move out of the cell. Af you implement a class used as a column data type, you can use the default editor if your class supplies a constructor that ta!es a single argument of type String. Af you li!e having a te-t field as the editor for a cell, but want to customi?e it D perhaps to chec! user entered te-t more strictly or to react differently when the te-t is invalid D you can change the cell editor to use a formatted te-t field. The formatted te-t field can chec! the value either continuously while the user is typing or after the user has indicated the end of typing 4such as by pressing *nter7. The following code, ta!en from a demo named TableFTF=(itDemo.java, sets up a formatted te-t field as an editor that limits all integer values to be between E and 1EE. Bou can run TableFTF=(itDemo 4clic! the 'aunch button7 using 2ava3 Web #tart 4download 2(5 6 or later7. .r, to compile and run the e-ample yourself, consult the e-ample inde-.

The following code ma!es the formatted te-t field the editor for all columns that contain data of type -nteger.
table.setDe"ault=(itor.-nteger.class, ne, -nteger=(itor.7, 97700&

The -nteger=(itor class is implemented as a subclass of De"ault?ell=(itor that uses a JFormatte(TeEtFiel( instead of the JTeEtFiel( that De"ault?ell=(itor supports. At accomplishes this by first setting up a formatted te-t field to use an integer format and have the specified minimum and ma-imum values, using the $0A described in How to %se )ormatted Te-t )ields. At then overrides the De"ault?ell=(itor implementation of the getTable?ell=(itor?omponent, get?ell=(itor$alue, and stop?ell=(iting methods, adding the operations that are necessary for formatted te-t fields. The override of getTable?ell=(itor?omponent sets the formatted te-t field:s value property 4and not just the text property it inherits from JTeEtFiel(7 before the editor

is shown. The override of get?ell=(itor$alue !eeps the cell value as an -nteger, rather than, say, the ong value that the formatted te-t field:s parser tends to return. )inally, overriding stop?ell=(iting lets you chec! whether the te-t is valid, possibly stopping the editor from being dismissed. Af the te-t isn:t valid, your implementation of stop?ell=(iting puts up a dialog that gives the user the option of continuing to edit or reverting to the last good value. The source code is a bit too long to include here, but you can find it in -nteger=(itor.java.

/rinting
provides a simple $0A for printing tables. The easiest way to print out a table is to invo!e JTable.print with no arguments:
JTable tr+ { i" .S table.print.00 { S+stem.err.println."Fser cancelle( printing"0& % % catc* .java.a,t.print.8rinter=Eception e0 { S+stem.err."ormat."?annot print HsHn", e.getBessage.00& %

Anvo!ing print on a normal #wing application brings up a standard printing dialog bo-. 4.n a headless application, the table is simply printed.7 The return value indicates whether the user went ahead with the print job or cancelled it. JTable.print can throw java.a,t.print.8rinter=Eception, which is a chec!ed e-ception; that:s why the above e-ample uses a tr+ ... catc*. provides several overloads of print with various options. The following code from Table8rintDemo.java shows how to define a page header:
JTable BessageFormat *ea(er = ne, BessageFormat."8age {7,number,integer%"0& tr+ { table.print.JTable.8rintBo(e.F-T>6-DT:, *ea(er, null0& % catc* .java.a,t.print.8rinter=Eception e0 { S+stem.err."ormat."?annot print HsHn", e.getBessage.00& %

)or more sophisticated printing applications, use JTable.get8rintable to obtain a 8rintable object for the table. )or more on 8rintable, refer to the 0rinting lesson in the 8( ;raphics trail.

!-amples that Use Tables


This table lists e-amples that use JTable and where those e-amples are described. !-ample
SimpleTableDemo

Where &escribed "reating a

otes $ basic table with no custom model. (oes

#imple Table

not include code to specify column widths or detect user editing.

SimpleTableO SelectionDemo

$dds single selection and selection detection to SimpleTableDemo. ,y modifying the (etecting %ser program:s ; '6>?' FBN>S= =?T-'N and #elections ; '6>2'6>S= =?T-'N constants, you can e-periment with alternatives to the table default of allowing only rows to be selected. "reating a Table &odel $ basic table with a custom model.

TableDemo

TableFTF=(itDemo

%sing an *ditor &odifies TableDemo to use a custom editor to /alidate 4a formatted te-t field variant7 for all %ser *ntered -nteger data. Te-t &odifies TableDemo to use a custom editor %sing a "ombo 4a combo bo-7 for all data in the Sport ,o- as an column. $lso intelligently pic!s column *ditor si?es. %ses renderers to display tool tips for the sport cells. %sing .ther *ditors #pecifying Tool Tips for "ells, #pecifying Tool Tips for "olumn Headers, #orting and )iltering #orting and )iltering 0rinting &odifies TableDemo to have a cell renderer and editor that display a color and let you choose a new one, using a color chooser dialog.

Table2en(erDemo

TableDialog=(itDemo

TableToolTipsDemo

(emonstrates how to use several techniCues to set tool tip te-t for cells and column headers.

TableSortDemo

(emonstrates the default sorter, which allows the user to sort columns by clic!ing on their headers. (emonstrates sorting and filtering, and how this can cause the view coordinates to diverge from the model coordinates. (emonstrates table printing.

TableFilterDemo Table8rintDemo istSelectionDemo

How to Write a #hows how to use all list selection modes, 'ist #election using a list selection listener that:s shared 'istener between a table and list. =owhere ,uilds on istSelectionDemo ma!ing the data model be shared between the table and list. Af you edit an item in the first column of the table, the new value is reflected in the

S*are(Bo(elDemo

list.

Potrebbero piacerti anche