JTable Key Bindings

I want to activate the save action anywhere in the application (Control + S). I added the necessary key binding, and the action starts as expected. However, if I try Control + S on JTable, the table will start my custom action and activate the table cell for editing. I think I disabled the edit action in the input table of the table. What am I missing here?

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; } } 
+2
source share
2 answers

Like @Guillaume, I had no problem running your code. You can find CellEditor , which inadvertently defeats editingStopped() , discussed here . sscce can help clarify the problem.

Addendum: you can cancel editing in the saveAction() handler, as shown below.

 table.editingCanceled(null); 

For reference, I updated your example in several respects:

  • Control-S is not tied to any JTable Action in common Look and Feel implementations, so there is no need to remove It.
  • For cross-platform convenience, use getMenuShortcutKeyMask() .
  • Swing GUI objects should only be created and processed in the event dispatch thread .

the code:

 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; } } 
+4
source

I finally figured it out. There is no key binding to the set, the action map does not exist. Thus, the appeals did nothing.

 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 passes the key event for editing CallAt there, running a table to enable editing. There are two ways. 1) Add an action link to the JTable input / action cards or 2) override editCellAt to return false. This is how I ran into the problem.

 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); } 
+1
source

Source: https://habr.com/ru/post/1413326/


All Articles