lbalazscs
lbalazscs

Reputation: 17784

JTable: single selection for the user, multiple selections programmatically

I have a JTable where the user should be able to select only a single row, but whenever a row is selected by the user, some other rows (that are related according to some logic) should also be selected programmatically. The problem is that if I set the selection mode of the table to ListSelectionModel.SINGLE_SELECTION, addRowSelectionInterval will also select only one row. Any ideas?

EDIT: I think all ideas (custom selection model, clearing all but last user selections, custom renderer for highlighting) were good, but the best is to use SwingX, because it doesn't require much infrastructure-code, only a clever usage of the library. (and it's easy to be clever when a SwingX-guru is helping :)

Upvotes: 1

Views: 6244

Answers (3)

kleopatra
kleopatra

Reputation: 51524

Biased me would say: certainly much easier in SwingX :-)

All you need is

  • a custom HighlightPredicate which decides about what is related
  • a ColorHighlighter configured with the selectionColors
  • set the custom predicate on receiving change notification from the selection model

Some code:

// the custom predicate
public static class RelatedHighlightPredicate implements HighlightPredicate {
    List<Integer> related;

    public RelatedHighlightPredicate(Integer... related) {
        this.related = Arrays.asList(related);

    }
    @Override
    public boolean isHighlighted(Component renderer,
            ComponentAdapter adapter) {
        int modelIndex = adapter.convertRowIndexToModel(adapter.row);
        return related.contains(modelIndex);
    }

}

// its usage
JXTable table = new JXTable(someModel);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
final ColorHighlighter hl = new ColorHighlighter(HighlightPredicate.NEVER, 
        table.getSelectionBackground(), table.getSelectionForeground());
table.addHighlighter(hl);
ListSelectionListener l = new ListSelectionListener() {

    @Override
    public void valueChanged(ListSelectionEvent e) {
        if (e.getValueIsAdjusting()) return;
        invokeUpdate((ListSelectionModel) e.getSource());
    }

    private void invokeUpdate(final ListSelectionModel source) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                int singleSelection = source.getMinSelectionIndex();
                if (singleSelection >= 0) {
                    int first = Math.max(0, singleSelection - 2);
                    int last = singleSelection + 2;
                    hl.setHighlightPredicate(new RelatedHighlightPredicate(first, last));
                } else {
                    hl.setHighlightPredicate(HighlightPredicate.NEVER);
                }
            }
        });

    }

};
table.getSelectionModel().addListSelectionListener(l);

Upvotes: 3

mKorbel
mKorbel

Reputation: 109815

  1. The problem is that if I set the selection mode of the table

    use ListSelectionModel.SINGLE_SELECTION for events came from mouse and keyborad

  2. some other rows (that are related according to some logic) should also be selected programmatically

    have look at Renderer for JTable, then required row(s), columns or whatever could be highlighted until programmatic rules stay unchanged

  3. ... maybe will help you

Upvotes: 2

Mikle Garin
Mikle Garin

Reputation: 10143

You might set multiselection possible for the table, but with each selection change - take only 1 (last selected) row, clear other selections and add your own computed selection.

Upvotes: 2

Related Questions