Question

Existe-t-il un moyen simple de manipuler les commandes d’une table JTable pour donner des fonctionnalités différentes lorsqu’un bouton du clavier est enfoncé (bouton CTRL, par exemple) et qu’une ligne est sélectionnée? On m'a demandé de créer une table où le CTRL + clic (clic de souris) sur une ligne désélectionnera uniquement une ligne sélectionnée, jamais une ligne. Si l'utilisateur CTRL + Clique sur une ligne non sélectionnée, rien ne se passera.

J'ai pu créer un tableau et désactiver des fonctions telles que CTRL + A (tout sélectionner) et j'ai pu vérifier si le bouton de contrôle est enfoncé lorsqu'un événement MouseEvent est généré, mais je ne peux pas. semble comprendre comment le CTRL + Click peut être ajusté. Voici du 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();
            }
        });
    }
}

Dans la méthode mousePressed, je me suis amusé à extraire toutes les lignes sélectionnées de la table et j'allais ensuite vérifier si la nouvelle ligne cliquée était dans les selectedRows ... Cependant, je ne suis pas sûr qu'il y en ait un moyen de voir quelle ligne est associée à MouseEvent.

(En outre, je sais que le comportement attendu, comme celui-ci, ne devrait pas être joué avec excès, mais c'est pour reproduire un système hérité de la société)

Toutes les idées / suggestions seraient appréciées!

Était-ce utile?

La solution

OK, deuxième prise (j'ai quitté le premier car cela pourrait intéresser quelqu'un pour un autre usage, qui sait? Dites-le, dites-le, il est là pour des raisons pédagogiques ...: -)).

J’ai jeté un œil au code source de JTable et découvert que les événements de la souris sont gérés par l’apparence. Sachant comment il gère la clé de contrôle, je pourrais remplacer en toute sécurité la méthode changeSelection pour faire ce dont vous avez besoin.
Je trouve les exigences un peu étranges (vous pouvez toujours utiliser les touches Maj + clic, non?), Mais je ne connais pas le contexte.

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);
    }
}

Beaucoup plus simple et exactement ce dont vous avez besoin!

BTW, merci de nous avoir fourni un si bon cas de test, je n’aurais peut-être pas essayé de l’écrire moi-même ... :-D C’était un défi intéressant et instructif.

Autres conseils

J'ai eu du succès avec ce qui suit, bien que je ne sois pas sûr que ce soit la meilleure méthode ...

class SpecialTable extends JTable
{
    boolean bIsControlDown;
    int clickedRow;

    SpecialTable(Object[][] data, String[] columnNames)
    {
        super(data, columnNames);
//        setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        getSelectionModel().addListSelectionListener(this);
        addMouseListener(new MouseInputAdapter()
        {
            public void mousePressed(MouseEvent me)
            {
                bIsControlDown = me.isControlDown();
                clickedRow = rowAtPoint(me.getPoint());
            }
        });
    }

    public void valueChanged(ListSelectionEvent evt)  
    {
        super.valueChanged(evt);
        if (bIsControlDown)
        {
            if (!evt.getValueIsAdjusting())
            {
//                System.out.println(evt);
//                System.out.println("=> " + clickedRow);
                getSelectionModel().removeSelectionInterval(clickedRow, clickedRow);
            }
        }
    }
}

Remplacez les lignes définissant la table dans votre code avec uniquement:

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

Lorsque vous cliquez avec le bouton droit de la souris sur une ligne non sélectionnée, celle-ci est brièvement sélectionnée, puis désélectionnée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top