JTable Check Boxes

40 views Asked by At

enter image description here

** [strong text][2]**

In this JTable for check boxes if I checked

  • case 1: "cricket" or "Chess" checked, then I want unchecked "football"
  • case 2: "football" checked, then I want unchecked both "cricket" and "Chess"

Please help for checkbox logic.

import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.*;
import javax.swing.table.*;

public final class JCheckExample extends JPanel {
    int trc;
    private final String[] columnNames = {"ID", "Name", "cricket","chess", "football"};
    private final Object[][] data = {{0,"Ram", false,false,true},
                                     {1,"Robert", true,false,false},
                                     {2,"Gopal", false,true,false},
                                     {3,"Rahim", true,true,false}};
    private final TableModel model = new DefaultTableModel(data, columnNames) {
        @Override
        public Class getColumnClass(int column) {
            return getValueAt(0, column).getClass();
        }
    };
    private final JTable table = new JTable(model);
    private final JScrollPane scrollPane = new JScrollPane(table);  

    public JCheckExample() {
        super(new BorderLayout());
        add(scrollPane);     
        JToggleButton check = new JToggleButton("Game Selection");
        check.addActionListener(ae -> {
            scrollPane.setVisible(!((JToggleButton)ae.getSource()).isSelected());
            scrollPane.revalidate();
        });
          add(check, BorderLayout.NORTH);
       }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Action Setting");
        frame.setSize(375, 300);     
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new JCheckExample());      
        frame.setVisible(true);
    }
}
1

There are 1 answers

1
Abra On

I suggest that you add a listener to the JTable model. Note that TableModelListener is a functional interface and therefore (since JDK 8) can be implemented via a method reference. With a method reference, you can name the method whatever and use whatever access modifier you like, the method just needs to take the same parameters as the interface method and return the same value. For method tableChanged (of interface TableModelListener) this means that the method needs to return void and take a single parameter of type TableModelEvent. In the below code, I have named the method adjustCheckBoxes.

Whenever one of the check-boxes in the JTable is changed, method adjustCheckBoxes will be called. The method implements the required logic as described (and understood by me) in your question.

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

public class JCheckExample extends JPanel {
    int trc;
    private final String[] columnNames = {"ID", "Name", "cricket", "chess", "football"};
    private final Object[][] data = {{0, "Ram", false, false, true},
                                     {1, "Robert", true, false, false},
                                     {2, "Gopal", false, true, false},
                                     {3, "Rahim", true, true, false}};
    private final TableModel model = new DefaultTableModel(data, columnNames) {
        @Override
        public Class<?> getColumnClass(int column) {
            return getValueAt(0, column).getClass();
        }
    };
    private final JTable table = new JTable(model);
    private final JScrollPane scrollPane = new JScrollPane(table);

    public JCheckExample() {
        super(new BorderLayout());
        add(scrollPane);
        JToggleButton check = new JToggleButton("Game Selection");
        check.addActionListener(ae -> {
            scrollPane.setVisible(!((JToggleButton) ae.getSource()).isSelected());
            scrollPane.revalidate();
        });
        add(check, BorderLayout.NORTH);
        model.addTableModelListener(this::adjustCheckBoxes);
    }

    private void adjustCheckBoxes(TableModelEvent event) {
        int row = event.getFirstRow();
        int col = event.getColumn();
        if (row >= 0) {
            if (col == 4) {
                Boolean isFootball = (Boolean) model.getValueAt(row, col);
                if (isFootball) {
                    model.setValueAt(Boolean.FALSE, row, 2);
                    model.setValueAt(Boolean.FALSE, row, 3);
                }
            }
            else {
                if (col == 2 || col == 3) {
                    Boolean isNotFootball = (Boolean) model.getValueAt(row, col);
                    if (isNotFootball) {
                        model.setValueAt(Boolean.FALSE, row, 4);
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Action Setting");
        frame.setSize(375, 300);     
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new JCheckExample());      
        frame.setVisible(true);
    }
}

Edit

I will heed the advice of @kleopatra, as stated in her comment, and offer an alternative solution that uses a custom TableModel which contains the required check-box logic.

In the below code, I have removed the TableModelListener and have written class CbModel which is a custom TableModel. Note the overridden setValueAt method in class CbModel.

import java.awt.BorderLayout;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

@SuppressWarnings("serial")
public class JCheckExample extends JPanel {
    int trc;
    private final String[] columnNames = {"ID", "Name", "cricket", "chess", "football"};
    private final Object[][] data = {{0, "Ram", false, false, true},
                                     {1, "Robert", true, false, false},
                                     {2, "Gopal", false, true, false},
                                     {3, "Rahim", true, true, false}};
    private final TableModel model = new CbModel(data, columnNames) {
        @Override
        public Class<?> getColumnClass(int column) {
            return getValueAt(0, column).getClass();
        }
    };
    private final JTable table = new JTable(model);
    private final JScrollPane scrollPane = new JScrollPane(table);

    public JCheckExample() {
        super(new BorderLayout());
        add(scrollPane);
        JToggleButton check = new JToggleButton("Game Selection");
        check.addActionListener(ae -> {
            scrollPane.setVisible(!((JToggleButton) ae.getSource()).isSelected());
            scrollPane.revalidate();
        });
        add(check, BorderLayout.NORTH);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Action Setting");
        frame.setSize(375, 300);     
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new JCheckExample());      
        frame.setVisible(true);
    }
}

@SuppressWarnings("serial")
class CbModel extends DefaultTableModel {

    public CbModel(Object[][] data, Object[] columnNames) {
        super(data, columnNames);
    }

    @Override
    public Class<?> getColumnClass(int column) {
        return getValueAt(0, column).getClass();
    }

    @Override
    public void setValueAt(Object aValue, int row, int column) {
        if (row >= 0  &&  column > 1  &&  column < 5) {
            adjustCheckBoxes(aValue, row, column);
        }
        else {
            super.setValueAt(aValue, row, column);
        }
    }

    private void adjustCheckBoxes(Object aValue, int row, int column) {
        boolean changed = false;
        if (aValue instanceof Boolean) {
            Boolean checked = (Boolean) aValue;
            if (row >= 0  &&  column > 1  &&  column < 5) {
                @SuppressWarnings("unchecked")
                Vector<Object> rowVector = dataVector.elementAt(row);
                rowVector.setElementAt(aValue, column);
                changed = true;
                if (column == 4) {
                    Boolean isFootball = checked;
                    if (isFootball) {
                        rowVector.setElementAt(Boolean.FALSE, 2);
                        rowVector.setElementAt(Boolean.FALSE, 3);
                    }
                }
                else {
                    if (column == 2 || column == 3) {
                        Boolean isNotFootball = checked;
                        if (isNotFootball) {
                            rowVector.setElementAt(Boolean.FALSE, 4);
                        }
                    }
                }
            }
        }
        if (changed) {
            fireTableRowsUpdated(row, row);
        }
    }
}