javaswing

Keep row selection on mouse clicks on JTable


How can Swing tables keep current selection when the user clicks on a row – without Ctrl pressed, but as if it is the case?

A table you can experiment on:

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import java.awt.BorderLayout;

public class LoadedTableDemo {

    private static JTable table;

    public static void main(String[] args) {
        JFrame frame = new JFrame("JTable Example");
        frame.setContentPane(createMainPanel());
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private static JPanel createMainPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.add(createTableScroller());
        return panel;
    }

    private static JScrollPane createTableScroller() {
        JTable table = createTable();
        return new JScrollPane(table);
    }

    private static JTable createTable() {
        table = new JTable();
        table.setModel(createTableModel());
        return table;
    }

    private static DefaultTableModel createTableModel() {
        String[] columns = {"Name", "Age", "City"};
        Object[][] data = {
                {"Alice", 25, "New York"},
                {"Bob", 30, "Los Angeles"},
                {"Charlie", 22, "Chicago"},
                {"Diana", 28, "Houston"},
                {"Eve", 35, "Miami"}
        };
        DefaultTableModel model = new DefaultTableModel(data, columns) {
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };
        return model;
    }
}

Solution

  • You can achieve this by creating a small anonymous subclass of JTable and overriding its changeSelection method.

    This method is the hook that the table's UI uses to process selection changes from mouse clicks. By overriding it, you can force every click to behave like a Ctrl-click.

    The key is to always call the super method with the toggle parameter set to true. This tells the selection model to add or remove the row from the existing selection, rather than clearing it.

    Here's how you can modify your createTable() method:

    import javax.swing.ListSelectionModel; // Add this import
    
    // ... inside your LoadedTableDemo class
    
    private static JTable createTable() {
        table = new JTable() {
            @Override
            public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
                // Always toggle the selection state of the row.
                // This makes a simple click behave like a CTRL-click.
                super.changeSelection(rowIndex, columnIndex, true, false);
            }
        };
    
        table.setModel(createTableModel());
        // Ensure the selection mode allows for multiple selections.
        table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        return table;
    }
    

    Just replace your existing createTable() method with this one. Now, when you click on different rows, they will be added to the selection one by one. Clicking a selected row again will deselect it, mimicking the exact behavior of Ctrl+click.