Aquí podría ser tu PUBLICIDAD


Cambie el comportamiento de Ctrl + clic en una JTable

votos
5

¿Hay una manera fácil de manipular los controles en una JTable para dar una funcionalidad diferente cuando hay un botón del teclado presionado (es decir, el botón CTRL) y se selecciona una fila? Se me ha pedido que cree una tabla donde el CTRL + clic (clic del mouse) en una fila solo anulará la selección de una fila seleccionada, nunca seleccione una fila. Si el usuario CTRL + hace clic en una fila no seleccionada, no pasará nada.

He podido crear una tabla y desactivar funciones como CTRL + A (seleccionar todo), y he podido verificar si se presiona el botón de control cuando se genera un evento MouseEvent, pero parece que no puedo imaginarlo cómo se puede ajustar CTRL + clic. Aquí hay un código:

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

En el método mousePressed, jugué para obtener todas las filas seleccionadas de la tabla, y luego verificaría si la fila que acaba de hacer clic estaba en las filas seleccionadas ... Sin embargo, no estoy seguro de si hay alguna manera de ver qué fila está asociada con MouseEvent.

(Además, sé que un comportamiento esperado como este no debería jugarse demasiado, sino replicar un sistema heredado en la empresa)

¡Cualquier idea / sugerencia sería apreciada!

Publicado el 12/03/2009 a las 17:19
fuente por usuario Nicks
En otros idiomas...        العربية       

2 respuestas

votos
8

OK, segunda toma (dejé la primera ya que podría interesar a alguien para otro uso, ¿quién sabe ?, decir que está ahí para fines educativos ... :-)).

Eché un vistazo al código fuente de JTable y descubrí que los eventos del mouse son manejados por la apariencia. Al saber cómo maneja la tecla de control, pude anular de forma segura el método changeSelection para hacer lo que necesita.
Encuentro que los requisitos son un poco extraños (aún puedes usar Mayús + clic, ¿no?) Pero no sé el contexto.

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

¡Mucho más simple y exactamente lo que necesitas!

Por cierto, gracias por proporcionar un buen caso de prueba tan simple, tal vez no lo hubiera intentado si tuviera que escribirlo yo mismo ... :-D Fue un desafío interesante y de aprendizaje.

Respondida el 13/03/2009 a las 03:17
fuente por usuario PhiLho


Aquí podría ser tu PUBLICIDAD


votos
1

Tuve éxito con lo siguiente, aunque no estoy seguro de que sea el mejor método ...

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

Reemplace las líneas que definen tableen su código con solo:

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

Cuando hace clic con el botón secundario en una fila no seleccionada, se selecciona brevemente, luego se deselecciona.

Respondida el 12/03/2009 a las 06:58
fuente por usuario PhiLho