Java:如何从任何JComponent中删除默认击键?

Java:如何从任何JComponent中删除默认击键?,java,swing,jcombobox,key-bindings,keystroke,Java,Swing,Jcombobox,Key Bindings,Keystroke,我想控制哪些击键属于哪个Jcomponent。我甚至想知道如何删除与Jcomponent关联的默认击键,并用其他喜爱的击键替换它们 我遵循了这个甲骨文,它给出了一个JButton的例子,我试过了,效果很好,但是当我试着用它的时候,它不起作用 我所尝试的是删除空格键,即防止JComponent对空格键做出响应 我使用以下代码删除空格键: JComboBox也是如此 sizesComboBox.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "n

我想控制哪些击键属于哪个
Jcomponent
。我甚至想知道如何删除与
Jcomponent
关联的默认击键,并用其他喜爱的击键替换它们

我遵循了这个甲骨文,它给出了一个JButton的例子,我试过了,效果很好,但是当我试着用它的时候,它不起作用

我所尝试的是删除空格键,即防止JComponent对空格键做出响应

我使用以下代码删除空格键:

JComboBox也是如此

sizesComboBox.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "none");
但不起作用,它(JComboBox)仍然响应空格键

对于
firstButton
,我移除了空格键的效果;我添加了F键,这样当您按下键盘上的F键时,
firstButton
就会被按下,而不会响应空格(预期)。请注意,即使
firstButton
没有焦点(
JComponent.WHEN_IN_FOCUSED_WINDOW
)也会按F键

这是一个SSCCE代码,显示了我的示例:
注意:我故意没有将上面的代码行添加到第二个按钮“secondButton”中,因此默认情况下它仍然响应空格

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.*;

public class KeyStrokeTest extends JPanel
{

    JPanel widgetPanel;
    JPanel textAreaPanel;
    JButton firstButton;
    JButton secondButton;
    JTextArea textArea;
    JComboBox<Integer> sizesComboBox;

    public KeyStrokeTest()
    {
        firstButton = new JButton("First");
        firstButton.addActionListener(eventWatcher);
        firstButton.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "none");
        firstButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("F"), "F Key");
        firstButton.getActionMap().put("F Key", eventWatcher);

        secondButton = new JButton("Second");
        secondButton.addActionListener(eventWatcher);

        sizesComboBox = new JComboBox<>();
        sizesComboBox.addItemListener(new itemListenerClass());
        for (int i = 1; i <= 8; i++)
        {
            sizesComboBox.addItem(i);
        }
        sizesComboBox.setSelectedIndex(0);
        sizesComboBox.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "none");


        textArea = new JTextArea(0, 0);
        JScrollPane scrollTextArea = new JScrollPane(textArea);
        scrollTextArea.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        textArea.setEditable(false);

        widgetPanel = new JPanel();
        textAreaPanel = new JPanel(new BorderLayout());

        widgetPanel.add(firstButton);
        widgetPanel.add(secondButton);
        widgetPanel.add(sizesComboBox);

        textAreaPanel.add(scrollTextArea, BorderLayout.CENTER);

        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, textAreaPanel, widgetPanel);
        splitPane.setDividerLocation(280);
        splitPane.setResizeWeight(.5d);
        this.setLayout(new BorderLayout());
        this.add(splitPane);
    }
    AbstractAction eventWatcher = new AbstractAction()
    {
        @Override
        public void actionPerformed(ActionEvent ae)
        {
            Object source = ae.getSource();
            if (source == firstButton)
            {
                textArea.append("First button clicked\n");
            }
            if (source == secondButton)
            {
                textArea.append("Second button clicked\n");
            }
        }
    };

    private class itemListenerClass implements ItemListener
    {

        @Override
        public void itemStateChanged(ItemEvent e)
        {
            if (e.getSource() == sizesComboBox)
            {
                if (textArea != null)
                {
                    textArea.append("Item " + sizesComboBox.getSelectedItem() + "\n");
                }
            }
        }
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("KeyStroke Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 300);
        frame.add(new KeyStrokeTest(), BorderLayout.CENTER);
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                UIManager.put("swing.boldMetal", Boolean.FALSE);
                createAndShowGUI();
            }
        });
    }
}
为什么是两个

谢谢

但不起作用,它(JComboBox)仍然对空间作出响应 钥匙

您应该使用
JComponent。当关注组件的
InputMap
像这样时(您可能会注意到,我使用了
KeyEvent
KeyStroke.getKeyStroke(int-key,int-modifier,boolean-onRelease)
,因为它更可读,更不容易出错,例如键入错误的字符串参数等):

据我所知,其原因得到了很好的解释:

组件包含(或是)具有焦点的组件。这 输入映射通常用于复合组件—组件 其实现依赖于子组件。例如,
JTable
s 当聚焦组件的祖先时,使用
进行所有绑定
如果用户正在编辑,则向上箭头键(例如)仍然
更改选定的单元格

因此我推断,
JCombobox
是一个复合组件,因此我们需要正确的
InputMap
-
当聚焦组件的
的 另一点:如果您测试了上面的代码,您会注意到 从
JComboBox
pod中选择一个项目会产生两行 选择项目“4”
JTextArea
中的输出为

Item 4
Item 4
为什么是两个

正如@mKorbel(+1)所说,有两个事件可能发生:

  • 取消选择一个项目
  • 选择一个项目
这些事件成对发生,因为当我们选择新值时,旧值被取消选择。因此,我们必须检查这一点,并采取适当行动:

@Override
public void itemStateChanged(ItemEvent e)
{
   if(e.getStateChange()==ItemEvent.SELECTED) { 
       //am item was selected do something
   }
}
其他建议:

  • 不要在
    JFrame
    上调用
    setSize

  • 在设置可见之前和添加组件之后,使用适当的
    LayoutManager
    和/或覆盖
    getPreferredSize
    返回适合内容的
    Dimension
    s,并在
    JFrame
    上调用
    pack()


将键笔划指定给新名称许多未注销的绑定已经存在(或已注册)。您可能想查看一些提示,但您需要知道look and feel使用的键绑定的名称,才能使其工作到另一点:
ItemListener始终触发两个事件,必须确定是否选中/取消选中
sizesComboBox.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
        .put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,0,false), "none");
Item 4
Item 4
@Override
public void itemStateChanged(ItemEvent e)
{
   if(e.getStateChange()==ItemEvent.SELECTED) { 
       //am item was selected do something
   }
}