1

JTable.setAutoCreateRowSorter creates a TableRowSorter that works very well* except for one thing: it fires a sort even if there are modifiers on the MouseEvent. I found this out only after I added Rob's TableColumnManager. When you meta click (control+button1 on macOS) on the JTableHeader, you'll see the sort happen just before the column chooser popup pops up. I don't want the sort to fire at all if there are any modifiers.

Is there an easy way to make the MouseAdapter fire only if the MouseEvent has no modifiers (specifically, the meta modifier)? I don't want to put the column chooser somewhere else in the app where it won't be so obvious.

Below is my MCV example (sorry for not posting Rob's Class, see the above link). You can test the mouse modifier behavior (i.e., proof that modifiers are ignored by the row sorter) without referring to the TableColumnManager.

import javax.swing.*;
public class SorterChooser {
    private static void createAndShowGUI() {
        JFrame frame = new JFrame("SorterChooser");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Object[][] data = { {"a", "1"}, {"b", "3"}, {"c", "2"}, {"d", "4"} };
        String[] colnames = { "c1", "c2" };
        JTable tab = new JTable(data, colnames);
        JScrollPane sp = new JScrollPane(tab);
        tab.setAutoCreateRowSorter(true);
        new TableColumnManager(tab, true); // comment this out to demo mouse behavior
        frame.getContentPane().add(sp);
        frame.pack();
        frame.setVisible(true);
    }
    public static void main (String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
  • By well, I mean it handles model changes and many other things that I need (e.g., some columns are not allowed to be sortable).
Jeff Holt
  • 2,940
  • 3
  • 22
  • 29

1 Answers1

0

What I did was extend BaseTableHeaderUI. How I found out that extending it is what I need to do was the hard part:

  1. added a RowSorterListener to JTable.getRowSorter
  2. printed the call stack when sorterChanged was called
  3. call stack lays blame on javax.swing.plaf.basic.BasicTableHeaderUI for the sort event
  4. found the source code for BasicTableHeaderUI
  5. sorting performed only by BasicTableHeaderUI.MouseInputHandler
  6. Extended BasicTableHeaderUI.MouseInputHandler to call its super only if there are no modifiers
  7. set my table's JTableHeaderUI to the new class

Here's the modified SorterChooser.java:

import javax.swing.*;
public class SorterChooser {
    private static void createAndShowGUI() {
        JFrame frame = new JFrame("SorterChooser");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Object[][] data = { {"a", "1"}, {"b", "3"}, {"c", "2"}, {"d", "4"} };
        String[] colnames = { "c1", "c2" };
        JTable tab = new JTable(data, colnames);
        tab.getTableHeader().setUI(new SorterChooserTableHeaderUI());  // new code
        JScrollPane sp = new JScrollPane(tab);

        tab.setAutoCreateRowSorter(true);
        new TableColumnManager(tab, true);

        frame.getContentPane().add(sp);
        frame.pack();
        frame.setVisible(true);
    }
    public static void main (String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

And here's the extended BasicTableHeaderUI.java:

import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.plaf.basic.BasicTableHeaderUI;

public class SorterChooserTableHeaderUI extends BasicTableHeaderUI {

    public class MouseInputHandler extends BasicTableHeaderUI.MouseInputHandler {
        public void mouseClicked (MouseEvent ev) {
            if (ev.getModifiersEx() == 0)
                super.mouseClicked(ev);
        }
    }

    @Override
    protected MouseInputListener createMouseInputListener () {
        return new MouseInputHandler();
    }

}
Jeff Holt
  • 2,940
  • 3
  • 22
  • 29