我想在我的应用程序中的任何位置触发保存操作(Control + S)。我添加了必要的键绑定,操作按预期触发。但是,如果我在JTable上尝试Control + S,该表将启动我的自定义操作并激活表格单元格进行编辑。我想我已经在表的输入映射中禁用了编辑操作。我在这里缺少什么?
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;
}
}
答案 0 :(得分:4)
与@Guillaume一样,我运行代码没有问题。您可能会找到CellEditor
无意中击败editingStopped()
,讨论here。 sscce可能有助于澄清问题。
附录:您可以在saveAction()
处理程序中取消编辑,如下所示。
table.editingCanceled(null);
作为参考,我已在几个方面更新了您的示例:
JTable
Action
共同的Look&感觉实现,所以不需要remove它。 getMenuShortcutKeyMask()
。代码:
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;
}
}
答案 1 :(得分:2)
我终于明白了。没有设置键绑定,动作映射不存在。所以对put的调用没有做任何事情。
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通过触发表来启用编辑,将键事件传递给editCellAt。有两种方法可以解决这个问题。 1)向JTable的输入/动作映射添加动作引用,或者2)覆盖editCellAt以返回false。以下是我解决这个问题的方法。
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);
}