Using JButton in JTable

Objective
This tutorial will help you to dynamically use a list of JButton in a JTable. The case study is a module of searching client to edit the information about a client.
Assume that we have a table in the database which contains the information about clients as follow:

And at the interface level, the search form and its results is shown as a table of clients whose name contains the entered keyword: each row of the table represents the information of a client. The last two columns are two button to ‘edit’ or ‘delete’ the corresponding client.

If we click on an ‘edit’ button, a sub-form of editClient appears and presents the information of the selected client to edit. After update, the information of the updated client will be automatically updated in the table of search result.

Design

Static design
This module is designed in the architect of classical MVC model:
– At the level of model, we have only one class: Client
– At the level of control, we have only one class: ClientDAO
– At the level of view, we need two main classes: SearchClientFrm, EditClientFrm

The control class, ClientDAO, has three main functions:
– ArrayList<Client> searchClient(String key): search in the tblClient all client whose name contains the @key.
– void editClient(Client client): update information of the @client, except its @id
– void deleteClient(int id): delete the client from tblClient in the DB whose id is @id
Note that in this class, you have to modify the following code based on your database and your JDBC :

public ClientDAO(){
         if(con == null){
             String dbUrl = "jdbc:mysql://localhost:3306/hotel";
             String dbClass = "com.mysql.jdbc.Driver";

             try {
                 Class.forName(dbClass);
                 con = DriverManager.getConnection (dbUrl, "root", "12345678");
             }catch(Exception e) {
                 e.printStackTrace();
             }
         }
     } 

At the view level, the class of searchClientFrm has three explicite view objects:
– txtKey: to receive the entered keyword to search
– btnSearch: to search the clients who satisfy the search filter
– tblResult: to represent the search result
And three implicit view attributes:
– listClient: to represent the search result
– listEdit: to dynamically represent the list of edit button in the table
– listDelete: to dynamically representthe list of delete button in the table

The EditClientFrm has 5 text field attributes to represent 5 editable attribute of a client: name, address, tel, email, note; and two buttons: update and reset.

Dynamic design
The scenario of this modul is follow:
– The user enters a keyword and clicks on the search button on the SearchClientFrm.
– The method actionperformed() of this class is triggered: it detects that the search button is clicked, so it calls the method btnSearchClick().
– The method btnSearchClick() calls and passes the keyword to the method searchClient() of the clientDAO class.
– The method searchClient() searches all clients whose name contains the keyword. Then, calls the method new and setter of the entity class Client to encapsulate the object of Client to return to the btnSearchClick().
– The btnSearchClick() method update the listClient, listEdit, and listDelete into the result table and then, displays the form to the user.
– The user clicks on an edit button in the table.
– The actionperformed() method is invoked one more time, its detects that an edit button is clicked, then its call the function btnEditClick().
– The btnEditClick() calls and passes the parameters to the class EditClientFrm.
– The class EditClientFrm receives input parameter and displays them in the form to the user
– The user modifies some attributs and clicks on Update button
– The method actionperformed() of the class EditClientFRm is invoked. It detects that the btnUpdate button is clicked, then it calls the method btnUpdateClick().
– This method calls the setter method of the entity class Client to enveloppe the object and passes it to the method editClient() of control class ClientDAO.
– The control class executes the function ecditClient() and return to the btnUpdateClick().
– This method call the method refrehResultAfterUpdate() of the class SearchClientFrm to automatically refresh the result table
– After refreshing the result table, the SearchClientFrm shows the form to the user.

Implementation

Client.java

 import java.io.Serializable;
 public class Client implements Serializable{
     private static final long serialVersionUID = 2018040801L;
     private int id;
     private String name;
     private String address;
     private String tel;
     private String email;
     private String note;
     public Client() {
         super();
     }
     public int getId() {
         return id;
     }
     public void setId(int id) {
         this.id = id;
     }
     public String getName() {
         return name;
     }
     public void setName(String name) {
         this.name = name;
     }
     public String getAddress() {
         return address;
     }
     public void setAddress(String address) {
         this.address = address;
     }
     public String getTel() {
         return tel;
     }
     public void setTel(String tel) {
         this.tel = tel;
     }
     public String getEmail() {
         return email;
     }
     public void setEmail(String email) {
         this.email = email;
     }
     public String getNote() {
         return note;
     }
     public void setNote(String note) {
         this.note = note;
     }    
 }

ClientDAO.java

import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.util.ArrayList;

 public class ClientDAO {
     private static Connection con;

     public ClientDAO(){
         if(con == null){
             String dbUrl = "jdbc:mysql://localhost:3306/hotel";
             String dbClass = "com.mysql.jdbc.Driver";

             try {
                 Class.forName(dbClass);
                 con = DriverManager.getConnection (dbUrl, "root", "12345678");
             }catch(Exception e) {
                 e.printStackTrace();
             }
         }
     }

     /**
      * search all clients in the tblClient whose name contains the @key
      * @param key
      * @return list of client whose name contains the @key
      */
     public ArrayList<Client> searchClient(String key){
         ArrayList<Client> result = new ArrayList<Client>();
         String sql = "SELECT * FROM tblClient WHERE name LIKE ?";
         try{
             PreparedStatement ps = con.prepareStatement(sql);
             ps.setString(1, "%" + key + "%");
             ResultSet rs = ps.executeQuery();

             while(rs.next()){
                 Client client = new Client();
                 client.setId(rs.getInt("id"));
                 client.setName(rs.getString("name"));
                 client.setAddress(rs.getString("address"));
                 client.setTel(rs.getString("tel"));
                 client.setEmail(rs.getString("email"));
                 client.setNote(rs.getString("note"));
                 result.add(client);
             }
         }catch(Exception e){
             e.printStackTrace();
         }    
         return result;
     }

     /**
      * update the @client
      * @param client
      */
     public void editClient(Client client){
         String sql = "UPDATE tblClient SET name=?, address=?, tel=?, email=?, note=? WHERE id=?";
         try{
             PreparedStatement ps = con.prepareStatement(sql);
             ps.setString(1, client.getName());
             ps.setString(2, client.getAddress());
             ps.setString(3, client.getTel());
             ps.setString(4, client.getEmail());
             ps.setString(5, client.getNote());
             ps.setInt(6, client.getId());

             ps.executeUpdate();
         }catch(Exception e){
             e.printStackTrace();
         }
     }

     /**
      * delete the client whose id is @id
      * @param id
      */
     public void deleteClient(int id){
         String sql = "DELETE FROM tblClient WHERE id=?";
         try{
             PreparedStatement ps = con.prepareStatement(sql);
             ps.setInt(1, id);

             ps.executeUpdate();
         }catch(Exception e){
             e.printStackTrace();
         }
     }
 }

SearchClientFrm.java

 import java.awt.Component;
 import java.awt.Dimension;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.util.ArrayList;

 import javax.swing.BoxLayout;
 import javax.swing.JButton;
 import javax.swing.JFrame;
 import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
 import javax.swing.JTable;
 import javax.swing.JTextField;
 import javax.swing.table.DefaultTableModel;
 import javax.swing.table.TableCellRenderer;
 public class SearchClientFrm extends JFrame implements ActionListener{
     private ArrayList<Client> listClient;
     private ArrayList<JButton> listEdit, listDelete;
     private JTextField txtKey;
     private JButton btnSearch;
     private JTable tblResult;

     public SearchClientFrm(){
         super("Search Client Demo");
         listClient = new ArrayList<Client>();
         listEdit = new ArrayList<JButton>();
         listDelete = new ArrayList<JButton>();

         JPanel pnMain = new JPanel();
         pnMain.setSize(this.getSize().width-5, this.getSize().height-20);        
         pnMain.setLayout(new BoxLayout(pnMain,BoxLayout.Y_AXIS));

         JPanel pn1 = new JPanel();
         pn1.setLayout(new BoxLayout(pn1,BoxLayout.X_AXIS));
         pn1.setSize(this.getSize().width-5, 20);
         pn1.add(new JLabel("Keyword: "));
         txtKey = new JTextField();
         pn1.add(txtKey);
         btnSearch = new JButton("Search");
         btnSearch.addActionListener(this);
         pn1.add(btnSearch);
         pnMain.add(pn1);

         JPanel pn2 = new JPanel();
         pn2.setLayout(new BoxLayout(pn2,BoxLayout.Y_AXIS));
         tblResult = new JTable(new ClientTableModel());
         JScrollPane scrollPane= new  JScrollPane(tblResult);
         tblResult.setFillsViewportHeight(false); 
         scrollPane.setPreferredSize(new Dimension(scrollPane.getPreferredSize().width, 250));

         TableCellRenderer buttonRenderer = new JTableButtonRenderer();
         tblResult.getColumn("Edit").setCellRenderer(buttonRenderer);
         tblResult.getColumn("Delete").setCellRenderer(buttonRenderer);
         tblResult.addMouseListener(new JTableButtonMouseListener(tblResult));
         pn2.add(scrollPane);
         pnMain.add(pn2);    
         this.add(pnMain);
         pnMain.setVisible(true);
         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     }

     @Override
     public void actionPerformed(ActionEvent e) {
         // TODO Auto-generated method stub
         JButton btnClicked = (JButton)e.getSource();
         if(btnClicked.equals(btnSearch)){
             btnSearchClick();
             return;
         }
         for(int i=0; i<listEdit.size(); i++)
             if(btnClicked.equals(listEdit.get(i))){
                 btnEditClick(i);
                 return;
             }
         for(int i=0; i<listDelete.size(); i++)
             if(btnClicked.equals(listDelete.get(i))){
                 btnDeleteClick(i);
                 return;
             }
     }

     /**
      * processing the event that the Search button is clicked
      */
     private void btnSearchClick(){
         if((txtKey.getText() == null)||(txtKey.getText().length() == 0))
             return;
         ClientDAO clientDAO = new ClientDAO();
         listClient = clientDAO.searchClient(txtKey.getText().trim());
         listEdit.clear();
        listDelete.clear(); 
         for(int i=0; i<listClient.size(); i++){
             JButton btn = new JButton("Edit");
             btn.addActionListener(this);
             listEdit.add(btn);
             btn = new JButton("Delete");
             btn.addActionListener(this);
             listDelete.add(btn);

         }
         ((DefaultTableModel)tblResult.getModel()).fireTableDataChanged();
     }

     /**
      * processing the event that the @index Edit button is clicked
      * @param index
      */
     private void btnEditClick(int index){

         (new EditClientFrm(this, listClient.get(index), index)).setVisible(true);
     }

     /**
      * enable to refresh the result table after update a client from @Update form
      * @index: the index of updated client in the list
      * @Client: the updated client
      */
     public void refreshResultAfterUpdate(int index, Client client){
         listClient.remove(index);
         listClient.add(index, client);
         ((DefaultTableModel)tblResult.getModel()).fireTableDataChanged();
     }

     /**
      * processing the event that the @index Delete button is clicked
      * @param index
      */
     private void btnDeleteClick(int index){
         int dialogButton = JOptionPane.YES_NO_OPTION;
         int dialogResult = JOptionPane.showConfirmDialog (this, "Would  you like to delete this client?", "Warning", dialogButton);
         if(dialogResult == JOptionPane.YES_OPTION){
             ClientDAO clientDAO = new ClientDAO();
             clientDAO.deleteClient(listClient.get(index).getId());
             listClient.remove(index);
             listEdit.remove(index);
             listDelete.remove(index);
         }
         ((DefaultTableModel)tblResult.getModel()).fireTableDataChanged();
     }

     class ClientTableModel extends DefaultTableModel {
         private String[] columnNames = {"Id", "Name", "Address", "Tel", "Email", "Note", "Edit", "Delete"};
         private final Class<?>[] columnTypes = new  Class<?>[] {Integer.class, String.class, String.class,  String.class, 
                 String.class, String.class, JButton.class,  JButton.class};

         @Override public int getColumnCount() {
             return columnNames.length;
         }

         @Override public int getRowCount() {
             return listClient.size();
         }

         @Override public String getColumnName(int columnIndex) {
             return columnNames[columnIndex];
         }

         @Override public Class<?> getColumnClass(int columnIndex) {
             return columnTypes[columnIndex];
         }

         @Override public Object getValueAt(final int rowIndex, final int columnIndex) {
                 /*Adding components*/
             switch (columnIndex) {
                 case 0: 
                     return listClient.get(rowIndex).getId();
                 case 1: 
                     return listClient.get(rowIndex).getName();
                 case 2: 
                     return listClient.get(rowIndex).getAddress();
                 case 3: 
                     return listClient.get(rowIndex).getTel();
                 case 4: 
                     return listClient.get(rowIndex).getEmail();
                 case 5: 
                     return listClient.get(rowIndex).getNote();
                 case 6: 
                     return listEdit.get(rowIndex);
                 case 7: 
                     return listDelete.get(rowIndex);                    
                 default: return "Error";
             }
         } 
     }

     class JTableButtonMouseListener extends MouseAdapter {
         private final JTable table;

         public JTableButtonMouseListener(JTable table) {
             this.table = table;
         }

         public void mouseClicked(MouseEvent e) {
             int column = table.getColumnModel().getColumnIndexAtX(e.getX()); // get the coloum of the button
             int row    = e.getY()/table.getRowHeight(); //get the row of the button

                     //*Checking the row or column is valid or not
             if (row < table.getRowCount() && row >= 0  && column < table.getColumnCount() && column >= 0)  {
                 Object value = table.getValueAt(row, column);
                 if (value instanceof JButton) {
                     //perform a click event
                     ((JButton)value).doClick();
                 }
             }
         }
     }

     class JTableButtonRenderer implements TableCellRenderer {        
         @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, 
                 boolean hasFocus, int row, int column) {
             JButton button = (JButton)value;
             return button;  
         }
     }

     /**
      * @param args
      */
     public static void main(String[] args) {
         // TODO Auto-generated method stub
         SearchClientFrm myFrame = new SearchClientFrm();
         myFrame.setSize(600,300);                
         myFrame.setVisible(true);                
         myFrame.setLocation(200,10);
     }
 }

EditClientFrm.java

import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.WindowEvent;

 import javax.swing.JButton;
 import javax.swing.JFrame;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JTextField;

 public class EditClientFrm extends JFrame implements ActionListener{
     private SearchClientFrm parent;
     private Client client;
     private int index;
     private JTextField txtId, txtName, txtAddress, txtTel, txtEmail, txtNote;
     private JButton btnUpdate, btnReset;


     public EditClientFrm(SearchClientFrm parent, Client client, int index){
         super("Edit a client");
         this.parent = parent;
         this.client = client;
         this.index = index;

         txtId = new JTextField(15);
         txtId.setEditable(false);
         txtName = new JTextField(15);
         txtAddress = new JTextField(15);
         txtTel = new JTextField(15);
         txtEmail = new JTextField(15);
         txtNote = new JTextField(15);
         btnUpdate = new JButton("Update");
         btnReset = new JButton("Reset");

         JPanel content = new JPanel();
         content.setLayout(new GridLayout(7,2));
         content.add(new JLabel("ID:"));     content.add(txtId);
         content.add(new JLabel("Name:"));     content.add(txtName);
         content.add(new JLabel("Address:"));     content.add(txtAddress);
         content.add(new JLabel("Tel:"));     content.add(txtTel);
         content.add(new JLabel("Email:"));     content.add(txtEmail);
         content.add(new JLabel("Note:"));     content.add(txtNote);
         content.add(btnUpdate);     content.add(btnReset);

         btnUpdate.addActionListener(this);
         btnReset.addActionListener(this);

         initForm();

         this.setContentPane(content);
         this.pack();
         this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
     }

     private void initForm(){
         if(client != null){
             txtId.setText(client.getId()+"");
             txtName.setText(client.getName());
             txtAddress.setText(client.getAddress());
             txtTel.setText(client.getTel());
             txtEmail.setText(client.getEmail());
             txtNote.setText(client.getNote());
         }
     }

     @Override
     public void actionPerformed(ActionEvent e) {
         // TODO Auto-generated method stub
         JButton btnClicked = (JButton)e.getSource();
         if(btnClicked.equals(btnReset)){
             initForm();
             return;
         }
         if(btnClicked.equals(btnUpdate)){
             btnUpdateClick();
         }
     }

     private void btnUpdateClick(){
         client.setName(txtName.getText());
         client.setAddress(txtAddress.getText());
         client.setTel(txtTel.getText());
         client.setEmail(txtEmail.getText());
         client.setNote(txtNote.getText());

         ClientDAO clientDAO = new ClientDAO();
         clientDAO.editClient(client);
         parent.refreshResultAfterUpdate(index, client);
         this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
     }
 } 

Leave a comment