Domanda

Esiste un modo semplice per manipolare i controlli su una JTable per fornire funzionalità diverse quando viene premuto un pulsante della tastiera (ad es. pulsante CTRL) e viene selezionata una riga? Mi è stato chiesto di creare una tabella in cui CTRL + clic (clic del mouse) su una riga deselezionerà solo una riga selezionata, non selezionerà mai una riga. Se l'utente CTRL + fa clic su una riga non selezionata, non accadrà nulla.

Sono stato in grado di creare una tabella e disabilitare funzioni come CTRL + A (seleziona tutto) e sono stato in grado di verificare se il pulsante di controllo viene premuto quando viene generato un MouseEvent, ma non posso sembra capire come sia possibile regolare CTRL + clic. Ecco un po 'di codice:

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

Nel metodo mousePressed ho giocato con l'ottenimento di tutte le righe selezionate dal tavolo e quindi avrei verificato se la riga appena cliccata fosse nelle righe selezionate ... Tuttavia, non sono sicuro che ci sia un modo per vedere quale riga è associata a MouseEvent.

(Inoltre, so che comportamenti attesi come questo non dovrebbero essere giocati troppo, ma è replicare un sistema legacy in azienda)

Eventuali idee / suggerimenti sarebbero apprezzati!

È stato utile?

Soluzione

OK, secondo scatto (ho lasciato il primo perché potrebbe interessare qualcuno per qualche altro uso, chi lo sa? Dire che è lì per scopi educativi ... :-)).

Ho dato un'occhiata al codice sorgente di JTable e ho scoperto che gli eventi del mouse sono gestiti dall'aspetto grafico. Sapendo come gestisce la chiave di controllo, potrei tranquillamente ignorare il metodo changeSelection per fare ciò di cui hai bisogno.
Trovo i requisiti un po 'strani (puoi ancora usare Shift + clic, no?) Ma non conosco il contesto.

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

Molto più semplice ed esattamente ciò di cui hai bisogno!

A proposito, grazie per aver fornito un caso così semplice, non avrei potuto provare se avessi dovuto scriverlo da solo ... MrGreen Era una sfida interessante e di apprendimento.

Altri suggerimenti

Ho avuto successo con quanto segue, anche se non sono sicuro che sia il metodo migliore ...

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

Sostituisci le righe che definiscono table nel tuo codice solo con:

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

Quando fai clic tenendo premuto il tasto Ctrl su una riga non selezionata, questa viene brevemente selezionata, quindi non selezionata.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top