|
Tables
Like trees, tables in Swing are vast and powerful. They are primarily intended to be the popular “grid” interface to databases via Java Database Connectivity (JDBC, discussed in Thinking in Enterprise Java), and thus they have a tremendous amount of flexibility, which you pay for in complexity. There’s easily enough here to allow the creation of a full-blown spreadsheet application and could probably justify an entire book. However, it is also possible to create a relatively simple JTable if you understand the basics.
The JTable controls how the data is displayed, but the TableModel controls the data itself. So to create a JTable, you’ll typically create a TableModel first. You can fully implement the TableModel interface, but it’s simpler to inherit from the helper class AbstractTableModel:
//: c14:JTableDemo.java
// Simple demonstration of JTable.
// <applet code=Table width=350 height=200></applet>
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.table.*;
import javax.swing.event.*;
import com.bruceeckel.swing.*;
public class JTableDemo extends JApplet {
private JTextArea txt = new JTextArea(4, 20);
// The TableModel controls all the data:
class DataModel extends AbstractTableModel {
Object[][] data = {
{"one", "two", "three", "four"},
{"five", "six", "seven", "eight"},
{"nine", "ten", "eleven", "twelve"},
};
// Prints data when table changes:
class TML implements TableModelListener {
public void tableChanged(TableModelEvent e) {
txt.setText(""); // Clear it
for(int i = 0; i < data.length; i++) {
for(int j = 0; j < data[0].length; j++)
txt.append(data[i][j] + " ");
txt.append("\n");
}
}
}
public DataModel() { addTableModelListener(new TML());}
public int getColumnCount() { return data[0].length; }
public int getRowCount() { return data.length; }
public Object getValueAt(int row, int col) {
return data[row][col];
}
public void setValueAt(Object val, int row, int col) {
data[row][col] = val;
// Indicate the change has happened:
fireTableDataChanged();
}
public boolean isCellEditable(int row, int col) {
return true;
}
}
public void init() {
Container cp = getContentPane();
JTable table = new JTable(new DataModel());
cp.add(new JScrollPane(table));
cp.add(BorderLayout.SOUTH, txt);
}
public static void main(String[] args) {
Console.run(new JTableDemo(), 350, 200);
}
} ///:~
DataModel contains an array of data, but you could also get the data from some other source such as a database. The constructor adds a TableModelListener that prints the array every time the table is changed. The rest of the methods follow the Beans naming convention (using “get” and “set” methods, which will be described later in this chapter) and are used by JTable when it wants to present the information in DataModel. AbstractTableModel provides default methods for setValueAt( ) and isCellEditable( ) that prevent changes to the data, so if you want to be able to edit the data, you must override these methods.
Once you have a TableModel, you only need to hand it to the JTable constructor. All the details of displaying, editing, and updating will be taken care of for you. This example also puts the JTable in a JScrollPane.
|
|