- Function: Provides an editable table on the screen. Rows
and columns are numbered starting with 0. The table holds objects
(not primitives). In the model property you can specify the object type
each column
is to have String, Integer, Double, etc. When you retrieve values
from
the table you will get an object back.
- Properties:
- AutoResizeMode - found under "other properties", if the JTable
is
placed inside a JScrollPane, then you'll want to set this to "off",
otherwise,
it will resize the cells so that they are all visible, making the
ScrollPane
useless. If no scrolll pane is used, then select one of the reize modes
so
that the cell sizes are changed so that they are all visible.
- AutoCreateRowSorter - automatically create a row sorter object
and attach to the table, allows the user to click on a column header
and have the contents of the table sorted by that column
- Model - use the model editor to setup the following
- number of rows and columns
- column titles
- default cell values
- valid data type
- and whether or not the column is editable
- if you want row titles, then set the first column so that it
is
not editable and its type is string. then enter the row titles in the
default
cell values.
- Methods:
- getColumnCount() - returns an integer number of the
columns
- getRowCount() - returns an integer number of the rows
- getSelectedRow() - retunrs an integer number of the row that
is
selected
- getSelectedColumn() - retunrs an integer number of the column
that
is selected
- setValueAt(Object value, int row, int col) - sets the value
of
a cell
- example myTable.setValueAt("1.23",0,0); // puts the value
1.23
in cell at the upper left corner
- getValueAt(int row, int col) - returns an object, that has
the
cell's value. this object can then be converted to a String, Integer,
Float,
etc, depending on how the table was setup, example
- String str = (String)myTable.getValueAt(0,0); // gets
cell
at upper left corner
- Integer iobj = (Integer)myTable.getValueAt(1,1); //
assumes column 1 has Integer data type
int i = iobj.intValue(); // gets the actual integer number
from
the Integer object
- Double dobj = (Double)myTable.getValueAt(1,2); // assumes
column 2 has a Double data type
double d = dobj.doubleValue(); // get actual double number
- NOTE : when a table is first created, any cell that does
not
have a default value is filled with null, therefore getValueAt will
return
a null. Therefore if you program is processing cells that might not be
initialized, then you should check for nulls, e.g.
if(myTable.getValueAt(1,1) != null)
// process the cell;
- getModel() - returns the TableModel, Netbeans automatically
creates
and attaches an object of type DefaultTableModel.
- other methods include the ability to print the contents of
the table
- Events:
- you probably won't need to process events for a table. If you
want to know whenever any cell has changed you can handle the table
changed event
coming from the table model listener, .... see below
/// JFrame Constructor
public NewJFrame() {
initComponents();
// add a listener to jTable1 that
will call a method whenever data has changed.
jTable1.getModel().addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
if(e.getType() == TableModelEvent.UPDATE)
cellChanged(e.getFirstRow(), e.getColumn());
}
});
}
//
// method to call when a cell has changed
//
public void cellChanged(int row,
int column)
{
System.out.println("cell "+row+","+column+" changed");
}
Other notes:
You'll notice that when you write code to process a button click this
code
will not get any value from the cell the user is currently working on.
The
problem is the little editor attached to the cell doesn't store the
value
in the cell until focus is shifted to another editing window (other
cell
or JTextField). This won't happen when menu items or buttons are
clicked
on (this allows things like cancel buttons to work even though someone
isn't
finished editing a cell, or the cell has invalid contents and doesn't
want
the focus to be shifted away).
The way it works is the table stores objects (Strings, Integers,
Doubles)
in each cell. Initially each cell has a null object. You should
provide
a default value for each cell (do this with the table model dialog or
with
a for loop in your constructor code). Without a default value, its
possible
when you access a cell's value you may get null back instead of an
object
(resulting in a null pointer exception). When a user is changing a cell
he/she
is actually typing into a small edit window (not the cell itself,
though
it looks that way), when editing focus is shifted away from that
editing
window, then the editing window verifies the contents against the data
type,
if the contents are ok, then a object of the proper type is created and
stored in the cell itself. If the contents are not ok (i.e. you
specified that the
column was to be of type Double and they entered "cat"), then the box
is
highlighted in red AND WHAT IS STORED IN THE CELL IS NOT CHANGED (any
value
that was there before is still there). At that point the user has the
ability
to fix the mistake or press the ESC key to restore the old value.
Because of this, when you process a menu or button press event, and a
cell
is being edited, then you will not get the value the user is currently
typing
in, intead you will get the old value (which might be null if you
didn't
setup default values for the cells). To get around this, all you have
to
do is to tell the JTable to edit a different cell.
Do this by using the editCellAt(row,col) command in your button
processing
method. Use -1,-1 or a cell you know to be safe. Note, this will
force
the little edit window to store what the user is currently typing into
the
cell (in unless the contents do not match the data type, in that event
you
get the old value and the user will see the value they are currently
working
on outlined in red). You can then access the value using getValueAt
private void
jButton1ActionPerformed(java.awt.event.ActionEvent
evt) {
// TODO add your handling
code
here:
jTable1.editCellAt(-1,-1);
//
force editing to cease, storing work in progress
String s1 =
jTable1.getValueAt(0,0).toString();
String s2 =
jTable1.getValueAt(0,1).toString();
String s3 =
jTable1.getValueAt(0,2).toString();
System.out.println(s1+"
"+s2+" "+s3);
}
An alternate solution to editCellAt, is to tell the table to stop
editing,
do this by calling editingCanceled with a change event. You'll need to
import
javax.swing.event.*; See below.
jTable1.editingCanceled(new
ChangeEvent(jTable1));
The draw back to this solution is that current editing changes are
discarded
(valid or invalid), and the documentation does not recommend calling
this
from within your program (though they did make the method public and it
does
seem to work). The advantage to editingCanceled is the table is left
displaying
the values you used in processing the button press, but since good
values
may be discarded, the user will likely be annoyed.
NimbusLookAndFeel - As of
version 7, Netbeans added code to JFrame Applications to use the Nimbus
Look and Feel as opposed to the default or system look and feel.
Unfortunately, past versions of Nimbus has/had errors, some of which
could effect JTables. To get rid of the Nimbus look and feell all
you need to do is to delete a section of code from the main method of
your JFrame application. Delete the code in red, don't delete the other
lines in the method.
public static void main(String args[])
{
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting
code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the
default look and feel.
* For details see
http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info :
javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE,
null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE,
null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE,
null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE,
null, ex);
}
//</editor-fold>
/* Create and display the
form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NewJFrame().setVisible(true);
}
});
}
Examples of processing JTables:
assume your JTable is named theTable and the cells
are
formatted as Integers
/*
* set all the table entries to zero
*/
for(int row = 0; row < theTable.getRowCount(); row++)
{
for(int col = 0; col < theTable.getColumnCount(); col++)
{
theTable.setValueAt(0,row,col); // set the
cell to a integer 0 (0.0 sets it to a double 0)
}
}
/*
* print all the row values to the output window
*/
for(int row = 0; row < theTable.getRowCount(); row++)
{
for(int col = 0; col < theTable.getColumnCount(); col++)
{
if(theTable.getValueAt(row,col)
!= null)
{
Integer aCell = (Integer)theTable.getValueAt(row,col);
System.out.print(aCell+", ");
}
}
System.out.println(""); // print a carriage return
at
the end of each row
}
/*
* calculate and print the average value of each row to the output
window
*/
for(int row = 0; row < theTable.getRowCount(); row++)
{
int sum = 0, average = 0;
for(int col = 0; col < theTable.getColumnCount(); col++)
{
if(theTable.getValueAt(row,col)
!= null)
{
Integer aCell =
(Integer)theTable.getValueAt(row,col);
sum = sum + aCell;
}
}
average = sum / theTable.getColumnCount();
System.out.println(" average = "+average); //
prints
average of each row, null values are assumed to be 0
}
JTable Model Objects
DefaultTableModel
- Function- Used to manipulate the rows and columns of
a
table. When you add a JTable to your application in NetBeans,
Netbeans
will generate the code to create the DefaultTable model (you don't have
to
do this yourself as you did with the JList).
- Useful Methods -
- addColumn(Object columnname) - adds a new column to the table
with
the specfied name
- addRow(Object[] rowdata) - adds a new row using the specified
data
to the table
- removeRow(int rownumber) - removes the specified row
- getRowCount() - returns the number of rows in the table
- getColumnCount() - returns the number of columns in the table
- getColumnName(int columnnumber) - returns the name of the
specified
column
- getValueAt(int row, int col) - retrieves the object at the
specified
row, column
- setValueAt(Object obj, int row, int col) - sets the specified
object
into the table
- setRowCount(int rows) - expands or shrinks the table to the
specfied
number of rows
- setColumnCount(int cols) - expands or shrinks the table to the
specified
number of columns
Examples:
private void
clearTableButtonActionPerformed(java.awt.event.ActionEvent
evt) {
// TODO add your handling code here:
int rows = theTable.getRowCount();
int columns = theTable.getColumnCount();
for(int r = 0; r < rows; r++)
for(int c = 0; c <
columns;
c++)
theTable.setValueAt("",r,c);
}
private void
removeRowButtonActionPerformed(java.awt.event.ActionEvent
evt) {
// TODO add your handling code here:
DefaultTableModel model =
(DefaultTableModel)theTable.getModel();
// get the table model
int row =
theTable.getSelectedRow();
if(row >= 0)
model.removeRow(row);
}
private void
addColumnButtonActionPerformed(java.awt.event.ActionEvent
evt) {
// TODO add your handling code here:
DefaultTableModel model =
(DefaultTableModel)theTable.getModel();
// get the table model
int columncount =
model.getColumnCount();
model.addColumn("Column
"+(columncount+1));
// add a new column
}
private void
addRowButtonActionPerformed(java.awt.event.ActionEvent
evt) {
// TODO add your handling code here:
DefaultTableModel model =
(DefaultTableModel)theTable.getModel();
// get the table model
int colcount =
theTable.getColumnCount();
// ask how many columns
Object data[] = new
Object[colcount];
// create an empty data array
model.addRow(data); //
add
the data as a new row
}
Printing JTables
the JTable component has a built in Print method that will all you to
send the contents of the JTablet to a printer. Its not necessary
to use PrinterJob or PageFormat objects, just call one of the print
method variations. Simple example:
try{
jTable1.print(javax.swing.JTable.PrintMode.FIT_WIDTH);
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(this,"Printing failed :"+ex.getMessage());
}
in this example the JTable is printed such that the it will fit on one
page width, but may span mutliple pages. Instead of using
FIT_WIDTH as the print mode you could use NORMAL, in that case the
table could span multiple pages in width.
Print modes
FIT_WIDTH - Printing mode that scales the output smaller, if necessary,
to fit the table's entire width (and thereby all columns) on each page;
Rows are spread across multiple pages as necessary.
NORMAL - Printing mode that prints the table at its current size,
spreading both columns and rows across multiple pages if necessary.
You can also printout headers and footers on each page, e.g.
try{
MessageFormat header = new
MessageFormat("Header Printout of my data ");
MessageFormat footer = new
MessageFormat("Footer ....");
jTable1.print(javax.swing.JTable.PrintMode.FIT_WIDTH, header, footer);
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(this,"Printing failed :"+ex.getMessage());
}