我尝试绑定JTable
的快捷方式,它可以正常使用Alphabets,但不适用于Insert
,Delete
,Space
这样的密钥等
对于Ex,以下代码适用于Ctrl+I
或任何字母表,但如果我选择Ctrl+Insert
它不能正常工作,为什么会这样?
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.table.DefaultTableModel;
public class NewClass {
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(NewClass.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(createTable()), BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static JTable createTable() {
DefaultTableModel tmodel = new DefaultTableModel(3, 5);
JTable table = new JTable(tmodel);
table.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_MASK), "Insert");
//Not working for VK_INSERT or VK_DELETE or VK_SPACE
table.getActionMap().put("Insert", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Insert Action");
}
});
return table;
}
}
更新1
使用WHEN_IN_FOCUSED_WINDOW
时无效,但如果我选择WHEN_FOCUSED
或WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
答案 0 :(得分:1)
WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
作为焦点的核心设置(隐藏在JScrolPane
s JViewport
后面)<强> JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT 强>
组件包含(或是)具有焦点的组件。此输入映射通常用于复合组件 - a 实现依赖于子组件的组件。对于 例如,JTables使用它们的所有绑定 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT如果用户正在编辑,则 向上箭头键(例如)仍然会更改所选单元格。
然后来自OPs问题和评论的所有KeyEvent
组合在Win7 / Win10,Java7 / Java8中正确地起作用,也来自MadProgrammer的删除帖子(users_rep&gt; 10k)
AFAIK有restiction,有多个修饰符,如果是&gt; 2,然后CTRL + ALT + SHIFT + Whatever
可以从AWTEventListener
或从非常复杂的KeyListener
SSCCE / MCVE表格中的模拟代码
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.table.DefaultTableModel;
public class NewClass {
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info
: javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException |
IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(
NewClass.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(createTable()), BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static JTable createTable() {
DefaultTableModel tmodel = new DefaultTableModel(3, 5);
JTable table = new JTable(tmodel);
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.CTRL_MASK), "Insert");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, KeyEvent.CTRL_MASK), "Insert");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, KeyEvent.CTRL_MASK), "Insert");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_MASK), "Insert");
table.getActionMap().put("Insert", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Action from JTable");
}
});
return table;
}
}
答案 1 :(得分:1)
没有选择
Delete Action from JTable
Insert Action from JTable
Space Action from JTable
I Action from JTable
选择单元格后
Delete Action from JTable
Insert Action from JTable
Space Action from JTable
I Action from JTable
从代码中,为了正确性是必需的(否则有一堆unilteres事件,但为了测试目的而完成)来测试CTRL&amp;&amp;无论是什么被压入内部的AWTEventListener
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
public class NewClass {
private JFrame frame = new JFrame();
private DefaultTableModel tmodel = new DefaultTableModel(3, 5);
private JTable table = new JTable(tmodel);
public NewClass() {
frame.add(new JScrollPane(createTable()), BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
if (event instanceof KeyEvent) {
KeyEvent ke = (KeyEvent) event;
Component comp = ke.getComponent();
if (comp instanceof JTable) {
System.out.println(comp);
} else if (comp instanceof JScrollPane) {
System.out.println(comp);
} else if (comp instanceof JViewport) {
System.out.println(comp);
} else if (comp instanceof JFrame) {
System.out.println(comp);
} else {
System.out.println(comp);
}
}
}
}, AWTEvent.KEY_EVENT_MASK);
}
public JTable createTable() {
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.CTRL_MASK), "Delete");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, KeyEvent.CTRL_MASK), "Insert");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, KeyEvent.CTRL_MASK), "Space");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_MASK), "I");
table.getActionMap().put("Delete", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Delete Action from JTable");
}
});
table.getActionMap().put("Insert", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Insert Action from JTable");
}
});
table.getActionMap().put("Space", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Space Action from JTable");
}
});
table.getActionMap().put("I", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("I Action from JTable");
}
});
return table;
}
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info
: javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException |
IllegalAccessException |
javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(
NewClass.class.getName()).log(
java.util.logging.Level.SEVERE, null, ex);
}
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new NewClass();
}
});
}
}
答案 2 :(得分:1)
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
import javax.swing.filechooser.*;
public class KeyBindings implements ItemListener {
private static final String PACKAGE = "javax.swing.";
private static final String[] COLUMN_NAMES = {"Action", "When Focused",
"When In Focused Window", "When Ancestor"};
private static String selectedItem;
private JComponent contentPane;
private JMenuBar menuBar;
private JTable table;
private JComboBox comboBox;
private Hashtable<String, DefaultTableModel> models;
public KeyBindings() {
models = new Hashtable<String, DefaultTableModel>();
contentPane = new JPanel(new BorderLayout());
contentPane.add(buildNorthComponent(), BorderLayout.NORTH);
contentPane.add(buildCenterComponent(), BorderLayout.CENTER);
resetComponents();
}
public JComponent getContentPane() {
return contentPane;
}
public JMenuBar getMenuBar() {
if (menuBar == null) {
menuBar = createMenuBar();
}
return menuBar;
}
private JComponent buildNorthComponent() {
comboBox = new JComboBox();
JLabel label = new JLabel("Select Component:");
label.setDisplayedMnemonic('S');
label.setLabelFor(comboBox);
JPanel panel = new JPanel();
panel.setBorder(new EmptyBorder(15, 0, 15, 0));
panel.add(label);
panel.add(comboBox);
return panel;
}
private String checkForUIKey(String key) {
if (key.endsWith("UI") && key.indexOf(".") == -1) {
String componentName = key.substring(0, key.length() - 2);
if (componentName.equals("PopupMenuSeparator")
|| componentName.equals("ToolBarSeparator")
|| componentName.equals("DesktopIcon")) {
return null;
} else {
return componentName;
}
}
return null;
}
private JComponent buildCenterComponent() {
DefaultTableModel model = new DefaultTableModel(COLUMN_NAMES, 0);
table = new JTable(model) {
private static final long serialVersionUID = 1L;
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
table.setAutoCreateColumnsFromModel(false);
table.getColumnModel().getColumn(0).setPreferredWidth(200);
table.getColumnModel().getColumn(1).setPreferredWidth(200);
table.getColumnModel().getColumn(2).setPreferredWidth(200);
table.getColumnModel().getColumn(3).setPreferredWidth(200);
Dimension d = table.getPreferredSize();
d.height = 350;
table.setPreferredScrollableViewportSize(d);
table.getTableHeader().setFocusable(true);
return new JScrollPane(table);
}
public void resetComponents() {
models.clear();
Vector<String> comboBoxItems = new Vector<String>(50);
UIDefaults defaults = UIManager.getLookAndFeelDefaults();
for (Object key : defaults.keySet()) {
String componentName = checkForUIKey(key.toString());
if (componentName != null) {
comboBoxItems.add(componentName);
}
}
Collections.sort(comboBoxItems);
comboBox.removeItemListener(this);
comboBox.setModel(new DefaultComboBoxModel(comboBoxItems));
comboBox.setSelectedIndex(-1);
comboBox.addItemListener(this);
comboBox.requestFocusInWindow();
if (selectedItem != null) {
comboBox.setSelectedItem(selectedItem);
}
}
private JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
menuBar.add(createFileMenu());
menuBar.add(createLAFMenu());
return menuBar;
}
private JMenu createFileMenu() {
JMenu menu = new JMenu("Application");
menu.setMnemonic('A');
menu.addSeparator();
menu.add(new ExitAction());
return menu;
}
private JMenu createLAFMenu() {
ButtonGroup bg = new ButtonGroup();
JMenu menu = new JMenu("Look & Feel");
menu.setMnemonic('L');
String lafId = UIManager.getLookAndFeel().getID();
UIManager.LookAndFeelInfo[] lafInfo = UIManager.getInstalledLookAndFeels();
for (int i = 0; i < lafInfo.length; i++) {
String laf = lafInfo[i].getClassName();
String name = lafInfo[i].getName();
Action action = new ChangeLookAndFeelAction(laf, name);
JRadioButtonMenuItem mi = new JRadioButtonMenuItem(action);
menu.add(mi);
bg.add(mi);
if (name.equals(lafId)) {
mi.setSelected(true);
}
}
return menu;
}
@Override
public void itemStateChanged(ItemEvent e) {
String componentName = (String) e.getItem();
changeTableModel(getClassName(componentName));
selectedItem = componentName;
}
private String getClassName(String componentName) {
if (componentName.equals("TableHeader")) {
return PACKAGE + "table.JTableHeader";
} else {
return PACKAGE + "J" + componentName;
}
}
private void changeTableModel(String className) {
DefaultTableModel model = models.get(className);
if (model != null) {
table.setModel(model);
return;
}
model = new DefaultTableModel(COLUMN_NAMES, 0);
table.setModel(model);
models.put(className, model);
JComponent component = null;
try {// Hack so I don't have to sign the jar file for usage in Java Webstart
if (className.endsWith("JFileChooser")) {
component = new JFileChooser(new DummyFileSystemView());
} else {
Object o = Class.forName(className).newInstance();
component = (JComponent) o;
}
} catch (Exception e) {
Object[] row = {e.toString(), "", "", ""};
model.addRow(row);
return;
}
ActionMap actionMap = component.getActionMap();
Object[] keys = actionMap.allKeys();
if (keys == null) {
Object[] row = {"No actions found", "", "", ""};
model.addRow(row);
return;
}
for (int i = 0; i < keys.length; i++) {
Object key = keys[i];
if (key instanceof String) {
continue;
} else {
keys[i] = "";
}
}
Arrays.sort(keys);
for (int i = 0; i < keys.length; i++) {
Object key = keys[i];
if (key != "") {
Object[] row = {key, "", "", ""};
model.addRow(row);
}
}
updateModelForInputMap(model, 1,
component.getInputMap(JComponent.WHEN_FOCUSED));
updateModelForInputMap(model, 2,
component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW));
updateModelForInputMap(model, 3,
component.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT));
}
private void updateModelForInputMap(TableModel model, int column, InputMap inputMap) {
if (inputMap == null) {
return;
}
KeyStroke[] keys = inputMap.allKeys();
if (keys == null) {
return;
}
Hashtable<Object, String> actions = new Hashtable<Object, String>(keys.length);
for (int i = 0; i < keys.length; i++) {
KeyStroke key = keys[i];
Object actionName = inputMap.get(key);
Object value = actions.get(actionName);
if (value == null) {
actions.put(actionName, key.toString().replace("pressed ", ""));
} else {
actions.put(actionName, value + ", " + key.toString().replace("pressed ", ""));
}
}
for (int i = 0; i < model.getRowCount(); i++) {
String o = actions.get(model.getValueAt(i, 0));
if (o != null) {
model.setValueAt(o.toString(), i, column);
}
}
}
class ChangeLookAndFeelAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private String laf;
protected ChangeLookAndFeelAction(String laf, String name) {
this.laf = laf;
putValue(Action.NAME, name);
putValue(Action.SHORT_DESCRIPTION, getValue(Action.NAME));
}
@Override
public void actionPerformed(ActionEvent e) {
try {
JMenuItem mi = (JMenuItem) e.getSource();
JPopupMenu popup = (JPopupMenu) mi.getParent();
JRootPane rootPane = SwingUtilities.getRootPane(popup.getInvoker());
Component c = rootPane.getContentPane().getComponent(0);
rootPane.getContentPane().remove(c);
UIManager.setLookAndFeel(laf);
KeyBindings bindings = new KeyBindings();
rootPane.getContentPane().add(bindings.getContentPane());
SwingUtilities.updateComponentTreeUI(rootPane);
rootPane.requestFocusInWindow();
} catch (Exception ex) {
System.out.println("Failed loading L&F: " + laf);
System.out.println(ex);
}
}
}
class ExitAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public ExitAction() {
putValue(Action.NAME, "Exit");
putValue(Action.SHORT_DESCRIPTION, getValue(Action.NAME));
putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_X));
}
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
class DummyFileSystemView extends FileSystemView {
@Override
public File createNewFolder(File containingDir) {
return null;
}
@Override
public File getDefaultDirectory() {
return null;
}
@Override
public File getHomeDirectory() {
return null;
}
}
private static void createAndShowGUI() {
KeyBindings application = new KeyBindings();
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("Key Bindings");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setJMenuBar(application.getMenuBar());
frame.getContentPane().add(application.getContentPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
/*try {
SynthLookAndFeel laf = new SynthLookAndFeel();
UIManager.setLookAndFeel(laf);
KeyBindings bindings = new KeyBindings();
} catch (UnsupportedLookAndFeelException ex) {
Logger.getLogger(KeyBindings.class.getName()).log(Level.SEVERE, null, ex);
} */
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
}
}