Java - JButton in a JTable cell

Now we shall discuss how to include a JButton in a table cell.

ButtonJTable.java
 
/*
 * ButtonJTable.java
 *
 * Created on Aug 3, 2013, 02:57:58 PM
 */
package me.dhanoop.forblog;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

/**
 *
 * @author dhanoopbhaskar
 */
public class ButtonJTable extends javax.swing.JFrame {

    private JButton tableData = null;

    /** Creates new form ButtonJTable */
    public ButtonJTable() {
        initComponents();
        customizeTable();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // 
    private void initComponents() {

        dbScrollPane = new javax.swing.JScrollPane();
        dbTable = new javax.swing.JTable();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        dbTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Title 1"
            }
        ));
        dbScrollPane.setViewportView(dbTable);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(dbScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 226, javax.swing.GroupLayout.PREFERRED_SIZE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(dbScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE)
        );

        pack();
    }// 

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new ButtonJTable().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify
    private javax.swing.JScrollPane dbScrollPane;
    private javax.swing.JTable dbTable;
    // End of variables declaration

    private void customizeTable() {
        Object[] columnNames = new Object[1];
        columnNames[0] = "Button";
        String buttonString = "Click Me";
        Object[][] rowData = new Object[1][1];
        rowData[0][0] = buttonString;
        DefaultTableModel tableModel = new DBTableModel(rowData, columnNames);
        dbTable.setModel(tableModel);
        tableData = new JButton(buttonString);
        tableData.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(new JFrame(), "I'm clicked!", "ButtonJTable", JOptionPane.INFORMATION_MESSAGE);
            }
        });

        dbTable.getColumnModel().getColumn(0).setCellEditor(new ButtonCellEditor(new JCheckBox()));
        dbTable.getColumnModel().getColumn(0).setCellRenderer(new TableCellRenderer() {

            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                if (isSelected) {
                    setForeground(table.getSelectionForeground());
                    setBackground(table.getSelectionBackground());
                } else {
                    setForeground(table.getForeground());
                    setBackground(UIManager.getColor("Button.background"));
                }
                tableData.setText((value == null) ? "" : value.toString());
                return tableData;
            }
        });

        dbTable.updateUI();
    }
}

DBTableModel.java
 
package me.dhanoop.forblog;

import javax.swing.table.DefaultTableModel;

/**
 *
 * @author dhanoopbhaskar
 */
public class DBTableModel extends DefaultTableModel {

    public DBTableModel(Object[] columns) {
        super(columns, 0);
    }

    public DBTableModel(Object[][] data, Object[] columns) {
        super(data, columns);
    }

    @Override
    public boolean isCellEditable(int row, int column) {
        return true;
    }
}

The following is the key snippet in the program. 
Here we do mainly two things: 
(1) Changing the CellEditor of the ColumnModel of the column at position 0 (zero) of the table
(2) Changing the CellRenderer of the ColumnModel of the column at position 0 (zero) of the table. 
Unlike JComboBox and JCheckBox, for JButton we don't have a suitable constructor. 

public javax.swing.DefaultCellEditor(javax.swing.JTextField); 
public javax.swing.DefaultCellEditor(javax.swing.JCheckBox); 
public javax.swing.DefaultCellEditor(javax.swing.JComboBox); 

The above are the ONLY available constructors for DefaultCellEditor. Hence we have to create fully customized DefaultCellEditor for JButton.
 
    private void customizeTable() {
        Object[] columnNames = new Object[1];
        columnNames[0] = "Button";
        String buttonString = "Click Me";
        Object[][] rowData = new Object[1][1];
        rowData[0][0] = buttonString;
        DefaultTableModel tableModel = new DBTableModel(rowData, columnNames);
        dbTable.setModel(tableModel);
        tableData = new JButton(buttonString);
        tableData.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(new JFrame(), "I'm clicked!", "ButtonJTable", JOptionPane.INFORMATION_MESSAGE);
            }
        });

        dbTable.getColumnModel().getColumn(0).setCellEditor(new ButtonCellEditor(new JCheckBox()));
        dbTable.getColumnModel().getColumn(0).setCellRenderer(new TableCellRenderer() {

            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                if (isSelected) {
                    setForeground(table.getSelectionForeground());
                    setBackground(table.getSelectionBackground());
                } else {
                    setForeground(table.getForeground());
                    setBackground(UIManager.getColor("Button.background"));
                }
                tableData.setText((value == null) ? "" : value.toString());
                return tableData;
            }
        });

        dbTable.updateUI();
    }

Please find below an example of such a customized DefaultCellEditor

ButtonCellEditor.java
 
package me.dhanoop.forblog;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JOptionPane;
import javax.swing.JTable;

/**
 *
 * @author dhanoopbhaskar
 */
public class ButtonCellEditor extends DefaultCellEditor {

    private JButton button = null;
    private String buttonText = null;
    private boolean isClicked;

    public ButtonCellEditor(JCheckBox checkBox) {
        super(checkBox);
        button = new JButton();
        button.setOpaque(true);
        button.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                fireEditingStopped();
            }
        });
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value,
            boolean isSelected, int row, int column) {
        if (isSelected) {
            button.setForeground(table.getSelectionForeground());
            button.setBackground(table.getSelectionBackground());
        } else {
            button.setForeground(table.getForeground());
            button.setBackground(table.getBackground());
        }
        buttonText = (value == null) ? "" : value.toString();
        button.setText(buttonText);
        isClicked = true;
        return button;
    }

    @Override
    public Object getCellEditorValue() {
        if (isClicked) {
            JOptionPane.showMessageDialog(button, "I'm clicked!", "ButtonJTable", JOptionPane.INFORMATION_MESSAGE);
        }
        isClicked = false;
        return buttonText;
    }

    @Override
    public boolean stopCellEditing() {
        isClicked = false;
        return super.stopCellEditing();
    }

    @Override
    protected void fireEditingStopped() {
        super.fireEditingStopped();
    }
}




Post a Comment

0 Comments