View RSS Feed

Java Swing

How to use model for your table in Swing application

Rate this Entry
by , 12-09-2011 at 09:06 AM (7927 Views)
Swing provides a very flexible widget, it is the JTable. Using the JTable component, you can display tabular data in form of columns and rows, plus allowing the user to edit and save the data if needed.

Why need to use a model

The Java Swing architecture separates the view and the model of a UI component. The view is how the component is drawn on the screen and gets changed if the user interacts with the component. The model is how data is structured and organized. The model represents the actual data that a UI component conveys. The component renders its look and feel based on the data. When the data in model gets changed, the component updates its look and feel accordingly. Every UI component in Swing uses model, and so does the JTable.

Normally, you don’t need to create model for common components like JText, JLabel, JCombobox… because each component comes with a default model if you don’t specify a custom one.
For tables, if its purpose is to view the data only, you won’t need a custom model. However, if you want your table allows user to edit the data and save changes back, you probably need to create a custom model.
This article will help you to write a table model that allows the user to edit and save data.

The API for JTable's model

We will write the model class that extends the AbstractTableModel class. This class belongs to the package javax.swing.table, it implements necessary stuffs and our subclass should implement these three methods:


Java Code: The AbstractTableModel's methods need to be implemented
 public int getRowCount();
 public int getColumnCount();
 public Object getValueAt(int row, int column);


In addition, we should override the following three methods:


Java Code: The AbstractTableModel's methods need to be overrided
   public String getColumnName(int column)
   public boolean isCellEditable(int rowIndex, int columnIndex)
   public void setValueAt(Object value, int rowIndex, int columnIndex)


The implementation will be explained by comment in the code. So please keep reading on.

The sample program

To demonstrate the usage of table model, we will write a small program that shows contact information in a table. A contact has the following fields: First name, last name, email, address, telephone. The program allows user to add, edit and delete a contact. The program’s user interface should look like the following screenshot:

Name:  app.PNG
Views: 3317
Size:  11.1 KB
Figure: The sample program

This is how the program will work: upon start up, the contact table is empty. Click Add button, the program will append a new, empty row at the end of the table. Users can type text into the columns and hit Enter to save the data. User can edit the data anytime by clicking on the cell, typing text and hit Enter after done. A row can be deleted by selecting the row first, then click Delete button.

Defining the model data

The program stores contact information, so we define a Contact class with the fields mentioned above. The code is pretty straight forward, with private fields and getters and setters, as follow:


Java Code: The model class
public class Contact {
    private String firstName;
    private String lastName;
    private String email;
    private String address;
    private String telephone;
   
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public String getTelephone() {
        return telephone;
    }
    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }
}



Creating the table model

The following code illustrates the model class which extends the AbstractTableModel class and implements the methods we talked previously. The embedded comment explains everything well enough to help you understand the logic.


Java Code: The table model class
import java.util.ArrayList;
import java.util.List;

import javax.swing.table.AbstractTableModel;

public class ContactModel extends AbstractTableModel {

    /*
     * we define index numbers for columns in table
     * in order to return the right value in getValue() method
     * and update the right value in setValue() method
     */
    private static final int COLUMN_FIRST_NAME     = 0;
    private static final int COLUMN_LAST_NAME     = 1;
    private static final int COLUMN_EMAIL        = 2;
    private static final int COLUMN_ADDRESS     = 3;
    private static final int COLUMN_TELEPHONE     = 4;
   
    /**
     * the list contains contacts objects
     */
    private List<Contact> listContacts;
   
    /**
     * names for column header in table
     */
    private String[] columnNames;
   
    /**
     * Creates new instance of the model
     */
    public ContactModel() {
        // initializes contact list
        this.listContacts = new ArrayList<Contact>();
        // define column names
        columnNames = new String[] {"First Name", "Last Name",
                "Email", "Address", "Telephone"};
    }
   
    /**
     * returns the number of columns in the table
     */
    public int getColumnCount() {
        return columnNames.length;
    }
   
    /**
     * returns name of a specified column in the table
     */
   public String getColumnName(int column) {
       return columnNames[column];
   }   

   /**
    * returns the number of rows in the table
    */
    public int getRowCount() {
        return listContacts.size();
    }

    /**
     * this method will be used by the table component to get
     * value of a given cell at [row, column]
     */
    public Object getValueAt(int rowIndex, int columnIndex) {
        Object value = null;
       
        Contact contact = listContacts.get(rowIndex);
       
        switch (columnIndex) {
            case COLUMN_FIRST_NAME:
                value = contact.getFirstName();
                break;
            case COLUMN_LAST_NAME:
                value = contact.getLastName();
                break;
            case COLUMN_EMAIL:
                value = contact.getEmail();
                break;
            case COLUMN_ADDRESS:
                value = contact.getAddress();
                break;
            case COLUMN_TELEPHONE:
                value = contact.getTelephone();
                break;
        }
       
        return value;
    }
   
    /**
     * this method will be used by the table component when user edits
     * a given cell at [row, column]. The corresponding contact object
     * will be updated.
     */
    public void setValueAt(Object value, int rowIndex, int columnIndex) {
        Contact contact = listContacts.get(rowIndex);
       
        switch (columnIndex) {
            case COLUMN_FIRST_NAME:
                contact.setFirstName(value.toString());
                break;
            case COLUMN_LAST_NAME:
                contact.setLastName(value.toString());
                break;
            case COLUMN_EMAIL:
                contact.setEmail(value.toString());
                break;
            case COLUMN_ADDRESS:
                contact.setAddress(value.toString());
                break;
            case COLUMN_TELEPHONE:
                contact.setTelephone(value.toString());
                break;
        }       
    }
   
    /**
     * since every cell in the table is editable, we return true always
     */
   public boolean isCellEditable(int rowIndex, int columnIndex) {
       return true;
   }   
   
   /**
    * this method allows the program adds a empty contact, a new row
    * will be appended to the table.
    */
   public void addContact(Contact aContact) {
       this.listContacts.add(aContact);
   }
   
   /**
    * this method allows the program removes a selected row in the table,
    * the corresponding contact object in the contact list is removed also.
    */
   public void removeContact(int rowIndex) {
       this.listContacts.remove(rowIndex);
   }

}


The methods you should notice in the above class are:

  • getValueAt(): the method should be implemented correctly to return the value of a cell at a specified row and column.
  • setValueAt(): this method is to update the value edited by the user for a given cell, back to the model data.
  • isCellEditable(): this method decides which cells are editable, which are not. In our model, all cells are editable.


One important point is how the data stored in the model:


Java Code: The declaration of contact list
    private List<Contact> listContacts;


We create a collection of type List to store Contact objects. A Contact object can be added or removed only by the following two methods:


Java Code: The methods that manipulate the Contact objects
   public void addContact(Contact aContact)
   public void removeContact(int rowIndex)


We hide the variable of the collection, listContacts, by making it as a private member and provide only two methods mentioned above, to ensure the data is always manipulated properly.

Writing the sample program

We have defined the data and written the model class. Next we need to glue all these together in a small sample program. The code is as follow:


Java Code: The implementation of the sample program
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;

public class ContactApp extends JFrame {
   
    private JTable tableContact = new JTable();
    private ContactModel contactModel = new ContactModel();
    private JButton buttonAdd = new JButton("Add");
    private JButton buttonDelete = new JButton("Delete");
   
    public ContactApp() {
        super("Contact");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
       
        tableContact.setModel(contactModel);
       
        getContentPane().add(new JScrollPane(tableContact), BorderLayout.CENTER);
       
        buttonAdd.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                addContact();
            }
        });

        buttonDelete.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                deleteContact();
            }
        });
       
        JPanel panelButton = new JPanel();
        panelButton.setLayout(new FlowLayout());
        panelButton.add(buttonAdd);
        panelButton.add(buttonDelete);
       
        getContentPane().add(panelButton, BorderLayout.PAGE_END);
       
        pack();
       
        setLocationRelativeTo(null);
    }
   
    private void addContact() {
        contactModel.addContact(new Contact());
        contactModel.fireTableDataChanged();
    }
   
    private void deleteContact() {
        int rowIndex = tableContact.getSelectedRow();
        if (rowIndex >= 0) {
            contactModel.removeContact(rowIndex);
            contactModel.fireTableDataChanged();
           
        }
    }
   
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new ContactApp().setVisible(true);
            }
        });
    }
}


It is pretty simple and well written so you can understand what it does easily. It creates a frame which contains a table on the top and two buttons at the bottom. The model is instantiated upon its declaration:


Java Code: The instantiation of the ContactModel object
    private ContactModel contactModel = new ContactModel();


and it is set to the table’s model:


Java Code: Set the model object for the table
tableContact.setModel(contactModel);


On clicking the button “Add”, a new row will be appended at the end of the table, fill values for some cells and hit Enter. The data is automatically saved back into the model. The adding operation is invoked on the model object:


Java Code: Add a new contact
        contactModel.addContact(new Contact());


Select a row you want to delete, then click “Delete”, the selected row will be removed from the table, and the corresponding object will be deleted from the model’s data. The deleting operation is also invoked on the model object:


Java Code: Delete a contact
        contactModel.removeContact(rowIndex);


So far we created a small (and nice) program that allows user to edit data in tabular format. I hope you will find this article useful.

References

A great tutorial about JTable by Oracle:
How to Use Tables (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Swing Components)

Submit "How to use model for your table in Swing application" to Facebook Submit "How to use model for your table in Swing application" to Digg Submit "How to use model for your table in Swing application" to del.icio.us Submit "How to use model for your table in Swing application" to StumbleUpon Submit "How to use model for your table in Swing application" to Google

Updated 12-09-2011 at 03:35 PM by Java Swing

Categories
JTable , Model

Comments