how bindings actions java swing jtable key-bindings

java - bindings - Ataduras de teclas JTable



java swing keylistener (2)

Al igual que @Guillaume, no tuve problemas para ejecutar tu código. Puede buscar un CellEditor que inadvertidamente derrota editingStopped() , discutido aquí . Una sscce puede ayudar a aclarar el problema.

Adición: puede cancelar la edición en el controlador saveAction() , como se muestra a continuación.

table.editingCanceled(null);

Como referencia, he actualizado su ejemplo en varios aspectos:

  • Control-S no está vinculado a ninguna Action JTable en las implementaciones comunes Look & Feel, por lo que no es necesario eliminarlo .
  • Para una conveniencia multiplataforma, use getMenuShortcutKeyMask() .
  • Los objetos Swing GUI se deben construir y manipular solo en el hilo de envío del evento .

Código:

import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.KeyStroke; public class TestTableKeyBinding extends JFrame { private static final int MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); private JTable table; public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { TestTableKeyBinding test = new TestTableKeyBinding(); test.setVisible(true); } }); } TestTableKeyBinding() { super(); initUI(); addKeyBindings(); } private void initUI() { this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); String[] headers = new String[]{"apples", "bananas"}; String[][] data = new String[][]{{"1", "2"}, {"4", "6"}}; table = new JTable(data, headers); table.setCellSelectionEnabled(true); this.add(new JScrollPane(table)); this.pack(); this.setSize(new Dimension(300, 400)); } private void addKeyBindings() { //root maps InputMap im = this.getRootPane().getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); ActionMap am = this.getRootPane().getActionMap(); //add custom action im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, MASK), "save"); am.put("save", saveAction()); } private AbstractAction saveAction() { AbstractAction save = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog( TestTableKeyBinding.this.table, "Action Triggered."); table.editingCanceled(null); } }; return save; } }

Quiero activar una acción de guardado en cualquier lugar de mi aplicación (Control + S). Agregué el enlace de clave necesario y la acción se desencadena como se esperaba. Sin embargo, si intento Control + S en una JTable, la tabla inicia mi acción personalizada y activa la celda de la tabla para su edición. Creo que he desactivado la acción de edición en el mapa de entrada de la tabla. ¿Que me estoy perdiendo aqui?

import java.awt.Dimension; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.KeyStroke; import javax.swing.UIManager; public class TestTableKeyBinding extends JFrame{ JTable table; JScrollPane scroll; public static void main(String[] args){ TestTableKeyBinding test = new TestTableKeyBinding(); test.setVisible(true); } TestTableKeyBinding(){ super(); initUI(); addKeyBindings(); } void initUI(){ this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); String[] headers = new String[]{"apples", "bananas"}; String[][] data = new String[][]{{"1", "2"},{"4","6"}}; table = new JTable(data, headers); table.setCellSelectionEnabled(true); scroll = new JScrollPane(); scroll.setViewportView(table); this.add(scroll); this.pack(); this.setSize(new Dimension(300, 400)); } void addKeyBindings(){ //root maps InputMap im = this.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); ActionMap am = this.getRootPane().getActionMap(); //add custom action im.put(KeyStroke.getKeyStroke("control S"), "save"); am.put("save", saveAction()); //disable table actions via ''none'' table.getInputMap().put(KeyStroke.getKeyStroke("control S"), "none"); table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("control S"), "none"); table.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("control S"), "none"); table.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control S"), "none"); ((InputMap)UIManager.get("Table.ancestorInputMap")).put(KeyStroke.getKeyStroke("control S"), "none"); } AbstractAction saveAction(){ AbstractAction save = new AbstractAction(){ public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub JOptionPane.showMessageDialog(TestTableKeyBinding.this.table, "Action Triggered."); } }; return save; } }


Finalmente lo resolví. No hay ningún enlace de clave para establecer, el mapa de acción no existe. Entonces las llamadas a poner no estaban haciendo nada.

table.getInputMap().put(KeyStroke.getKeyStroke("control S"), "none"); table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("control S"), "none"); table.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("control S"), "none"); table.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control S"), "none"); ((InputMap)UIManager.get("Table.ancestorInputMap")).put(KeyStroke.getKeyStroke("control S"), "none");

JTable pasa el evento clave para editarCELLAt allí activando la tabla para permitir la edición. Hay dos formas de evitar esto 1) Agregue una referencia de acción a los mapas de entrada / acción de JTable o 2) anule EditCellAt para devolver falso. Así es como supe el problema.

public boolean editCellAt(int row, int column, EventObject e){ if(e instanceof KeyEvent){ int i = ((KeyEvent) e).getModifiers(); String s = KeyEvent.getModifiersExText(((KeyEvent) e).getModifiers()); //any time Control is used, disable cell editing if(i == InputEvent.CTRL_MASK){ return false; } } return super.editCellAt(row, column, e); }