javacavaj
javacavaj

Reputation: 2971

Multiple Tables Single Selection

I'm developing an application that utilizes a group of JTables each backed a by distinct data model (e.g., different object in each table). The use case requires a multiple-exclusion scope for the set of tables (i.e., at most 1 row per group of tables can be selected at any given point).

The JDK ButtonGroup implements this functionality for a group of AbstractButtons. Has anyone seen and analogous implementation for tables? If not, is this the best approach to pursue? Perhaps, there is a better design pattern/idiom.

Upvotes: 2

Views: 503

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285405

You would have to roll your own, but this can be done by using a custom ListSelectionListener. Something like this could work:

@Override
public void valueChanged(ListSelectionEvent e) {
    ListSelectionModel selectedModel = (ListSelectionModel) e.getSource();
    for (ListSelectionModel model : models) {
        if (model != selectedModel) {
            model.removeListSelectionListener(this);
            model.clearSelection();
            model.addListSelectionListener(this);
        }
    }
}   

Where models is an ArrayList that holds the ListSelectionModels for all your JTables.

For example:

import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;

@SuppressWarnings("serial")
public class ListSelectionListenerExample extends JPanel {
    private static final int TABLE_COUNT = 4;
    private static final Integer[][] DATA = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    private static final String[] COL_NAMES = {"A", "B", "C"};

    public ListSelectionListenerExample() {
        ListSelectionGroup listSelectionGroup = new ListSelectionGroup();
        setLayout(new GridLayout(1, 0));
        for (int i = 0; i < TABLE_COUNT; i++) {
            DefaultTableModel model = new DefaultTableModel(DATA, COL_NAMES);
            JTable table = new JTable(model);
            ListSelectionModel selectionModel = table.getSelectionModel();
            listSelectionGroup.register(selectionModel);
            add(new JScrollPane(table));
        }
    }

    private static void createAndShowGui() {
        ListSelectionListenerExample mainPanel = new ListSelectionListenerExample();

        JFrame frame = new JFrame("ListSelectionListener Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

import java.util.ArrayList;
import java.util.List;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class ListSelectionGroup {

    private List<ListSelectionModel> models = new ArrayList<>();
    private MyListener myListener = new MyListener();

    public void register(ListSelectionModel model) {
        models.add(model);
        model.addListSelectionListener(myListener);
    }

    // overload method for convenience
    public void register(JTable table) {
        register(table.getSelectionModel());
    }

    // make a private inner class so that we don't accidentally add this to a 
    // ListSelectionModel without going through the register method
    private class MyListener implements ListSelectionListener {

        @Override
        public void valueChanged(ListSelectionEvent e) {
            ListSelectionModel selectedModel = (ListSelectionModel) e.getSource();
            for (ListSelectionModel model : models) {
                if (model != selectedModel) {
                    model.removeListSelectionListener(this);
                    model.clearSelection();
                    model.addListSelectionListener(this);
                }
            }
        }
    }
}

Upvotes: 2

Related Questions