Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change the Ctrl + click behaviour on a JTable

Tags:

java

swing

jtable

Is there an easy way to manipulate the controls on a JTable to give different functionality when there is a keyboard button pressed (ie. CTRL button) and a row is selected? I've been asked to create a table where the CTRL + Click (mouse click) on a row will only deselect a selected row, never select a row. If the user CTRL + Clicks an unselected row, nothing will happen.

I've been able to create a table, and disable functions like CTRL + A (select all), and i've been able to check if the control button is pressed when a MouseEvent is generated, but I can't seem to figure out how the CTRL + Click can be adjusted. Here's some code:

package nicky;

import javax.swing.*;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.*;

public class TableTester extends JPanel {
    public TableTester() {
        super(new GridLayout(1,0));

        final String[] columnNames = {"First Name",
                                      "Last Name",
                                      "Sport",
                                      "# of Years",
                                      "Vegetarian"};

        final Object[][] data = {
            {"Tom",   "Roberts","Athletic", new Integer(5),  new Boolean(false)},
            {"Sarah", "Watt",   "Football", new Integer(3),  new Boolean(true)},
            {"Laura", "Brown",  "Swimming", new Integer(2),  new Boolean(false)},
            {"Simon", "Smith",  "Tennis",   new Integer(20), new Boolean(true)},
            {"Paul",  "Jones",  "Rugby",    new Integer(10), new Boolean(false)}
        };

        JTable table = new JTable(data, columnNames);
        table.setPreferredScrollableViewportSize(new Dimension(500, 100));

        table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);

        table.addMouseListener(new MouseListener(){
            public void mouseEntered(MouseEvent me){}
            public void mouseExited(MouseEvent me){}
            public void mouseReleased(MouseEvent me){}
            public void mouseClicked(MouseEvent me){}
            public void mousePressed(MouseEvent me){
                if (me.isControlDown()){
                    System.out.println("This is working ");
                }
            }
        });

        InputMap inputMap = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK);
        inputMap.put(keyStroke, "none");

        JScrollPane scrollPane = new JScrollPane(table);
        add(scrollPane);
    }

    private static void createAndShowGUI() {
        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("TableTester");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        TableTester newContentPane = new TableTester();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

In the mousePressed method I've played around with getting all the selected rows from the table, and was then going to check if the newly clicked row was in the selectedRows... However, I'm not sure if there is a way to see which row is associated with the MouseEvent.

(Also, I know expected behaviour such as this shouldn't be played around with too much, but it's to replicate a legacy system in the company)

Any ideas/suggestions would be appreciated!

like image 871
Nicks Avatar asked Mar 12 '09 16:03

Nicks


1 Answers

OK, second take (I left the first one as it might interest somebody for some other usage, who know? Say it is there for educational purpose... :-)).

I had a look at the source code of JTable and found out that mouse events are handled by the look and feel. Knowing how it handles the control key, I could safely override the changeSelection method to do what you need.
I find requirements a bit strange (you can still use Shift+click, no?) but I don't know context.

class SpecialTable extends JTable
{
    SpecialTable(Object[][] data, String[] columnNames)
    {
        super(data, columnNames);
// That's already the default        
//        setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    }

    /**
     * Called by javax.swing.plaf.basic.BasicTableUI.Handler.adjustSelection(MouseEvent)
     * like: table.changeSelection(pressedRow, pressedCol, e.isControlDown(), e.isShiftDown());
     */
    @Override
    public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend)
    {
        if (toggle && !isRowSelected(rowIndex))
            return; // Don't do the selection
        super.changeSelection(rowIndex, columnIndex, toggle, extend);
    }
}

Much simpler and exactly what you need!

BTW, thanks for providing such simple good test case, I might have not tried if I had to write it myself... :-D It was an interesting and learning challenge.

like image 89
PhiLho Avatar answered Oct 21 '22 05:10

PhiLho