|
|
The JTable class is used to display arrays of data. We found that the GUI object was very useful when we discussed how to integrate a database in Java in Chapter 16. Let's look at a sample application that will display a table of data. Note that this example requires two source files, one for the actual application and the other to handle the table.
Code Listing 16: Using the JTable
JTableExample.java
import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; public class JTableExample extends JFrame implements ActionListener { public static void main(String[] argv) { JTableExample mainApp = new JTableExample(); } public JTableExample() { super("JTable Example"); setBounds(0, 0, 450, 350); getContentPane().setLayout(null); setDefaultCloseOperation(EXIT_ON_CLOSE); table = new JTable(10, 3); table.setBounds(10, 10, 420, 200); tableHandler = new TableHandler(); table.setModel(tableHandler); // Create three JTextField... textfield1 = new JTextField(15); textfield1.setLocation(10, 220); textfield1.setSize(textfield1.getPreferredSize()); textfield2 = new JTextField(15); textfield2.setLocation(10, 250); textfield2.setSize(textfield2.getPreferredSize()); textfield3 = new JTextField(15); textfield3.setLocation(10, 280); textfield3.setSize(textfield3.getPreferredSize()); // Create the button... addButton = new JButton("Add Data to Table"); addButton.setLocation(200, 220); addButton.setSize(addButton.getPreferredSize()); // Add the action listeners... addButton.addActionListener(this); // Add the objects to the content pane... getContentPane().add(table); getContentPane().add(textfield1); getContentPane().add(textfield2); getContentPane().add(textfield3); getContentPane().add(addButton); setVisible(true); } public void actionPerformed(ActionEvent e) { if(e.getSource() == addButton) { // Check there is text in the 'textfield' if(textfield1.getText().compareTo("") != 0 && textfield2.getText().compareTo("") != 0 && textfield3.getText().compareTo("") != 0) { // Then add the three fields to the JTable tableHandler.addRowToTable(textfield1.getText(), textfield2.getText(), textfield3.getText()); // Clear the textfields... textfield1.setText(""); textfield2.setText(""); textfield3.setText(""); } } } JTable table; TableHandler tableHandler; JTextField textfield1; JTextField textfield2; JTextField textfield3; JButton addButton; }
TableHandler.java
import javax.swing.table.*; import java.util.*; class TableHandler extends AbstractTableModel { public TableHandler() { dataRows = new Vector(); // set up the vector } public void addRowToTable(String a, String b, String c) { String[] rowData = new String[3]; rowData[0] = a; rowData[1] = b; rowData[2] = c; dataRows.addElement(rowData); // Add the data to a vector fireTableChanged(null); // Tell the table there is new data } public int getColumnCount() { return 3; } public int getRowCount() { if(dataRows != null) { return dataRows.size(); } else { return -1; } } public Object getValueAt(int row, int column) { if(dataRows != null) { return ((String[])(dataRows.elementAt(row)))[column]; } else { return null; } } private Vector dataRows; // Vector to contain the rows of data }
When we run the example and add some sample data into the table using the three text fields and the button, the following should be visible:
Figure 20: Using the JTable
Let's first look at our TableHandler class before we look at how we implemented it into the main class. Our TableHandler class extends the AbstractTableModel class, which is used by JTables to control how the data is stored for the table. The purpose of our TableHandler class is to allow functionality to the JTable, such as the addRowToTable method that we created to allow a row of data to be inserted easily into the table. Let's look at all the methods in the TableHandler one by one, so we can understand how it works.
The constructor
public TableHandler() { dataRows = new Vector(); // set up the vector }
The constructor only creates a new vector object, which is stored in the dataRows reference. This vector is used to hold all of our table data (i.e., the rows and columns).
The addRowToTable method
public void addRowToTable(String a, String b, String c) { String[] rowData = new String[3]; rowData[0] = a; rowData[1] = b; rowData[2] = c; dataRows.addElement(rowData); // Add the data to a vector fireTableChanged(null); // Tell the table there is new data }
The addRowToTable method allows us to easily add rows to our table by taking in three string parameters, which represent the three columns in the new table row. First we assign each of the three strings (a, b, and c) to an array of three strings called rowData. Once this is done, we add the reference to the array of three strings to our dataRows vector, which we initialized in the constructor. Finally, we call a method of the AbstractTableModel, which we have extended, called fireTableChanged. This method notifies the table that the data inside the table has changed. We will see how the table updates its data in the getValueAt method. If the table is large, the parameter in the fireTableChanged method, which is null in the example, should tell exactly what rows or columns are updated so that the table view is not completely updated unnecessarily.
The getColumnCount method
public int getColumnCount() { return 3; }
The getColumnCount method does exactly what it says; it simply returns the number of the columns in our table. We have hard-coded this value to be 3, but this can be worked out dynamically if required. Note that this method is part of the abstract class that we are extending and therefore must be implemented.
The getRowCount method
public int getRowCount() { if(dataRows != null) { return dataRows.size(); } else { return -1; } }
The getRowCount method simply returns the number of rows currently in the table by retrieving the size of our dataRows vector. If the dataRows vector is null, the function returns –1. Note that this method is also part of the AbstractTableModel that we are extending and consequently must be implemented.
The getValueAt method
public Object getValueAt(int row, int column) { if(dataRows != null) { return ((String[])(dataRows.elementAt(row)))[column]; } else { return null; } }
The getValueAt method is where the magic happens when we try to update the information in our table. This method is called by the JTable to retrieve the data that should be in each of its columns and rows once the fireTableChanged method is called. All this method does is return the string that is stored at the row and column that is specified by the two parameters the method takes (i.e., the integer's row and column). Note that this function is also part of the abstract class that we are extending; hence it must also be implemented. Note also, though, that if this function is not implemented correctly, no data will be visible in your table.
Now that we have looked at the TableHandler class, let's look at how it is implemented in our main JTableExample class. First we have created the JTable object with the following code segment:
table = new JTable(10, 3); table.setBounds(10, 10, 420, 200);
Note that the JTable constructor parameters represent the number of rows and columns that you wish to be visible on the screen.
Once the object is created, we then create an instance of our TableHandler class and store the reference in a variable called tableHandler. Then, once this is done, we call the setModel method of our table object to set its model to be our TableHandler class. This can be seen in the following code segment:
tableHandler = new TableHandler(); table.setModel(tableHandler);
Finally, if we look at the code where we handle the button click, we can see that all we have to do is retrieve the text that the user has entered into the text fields and pass them into the addRowToTable method, which is a member of our tableHandler object. Our table will automatically update after we call this method, as the addRowToTable method calls the fireTableChanged method after it has updated the vector in the TableHandler class. The use of the addRowToTable method can be seen in the following code snippet:
tableHandler.addRowToTable(textfield1.getText(), textfield2.getText(), textfield3.getText());
|
|