Java:如何从任何JComponent中删除默认的KeyStrokes?

我想控制哪个击键属于哪个Jcomponent.我甚至想知道如何删除与Jcomponent关联的认击键,并将其替换为其他喜欢的击键.

我跟着这个oracle tutorial,它给出了一个JButton的例子,我尝试了它并且工作正常,但是当我用JComboBox尝试它时它不起作用!

我试图删除SPACE键,这是为了防止JComponent响应SPACE按键

我用这段代码删除了SPACE键:

firstButton.getInputMap().put(Keystroke.getKeystroke("SPACE"),"none");

JComboBox也是如此

sizesComboBox.getInputMap().put(Keystroke.getKeystroke("SPACE"),"none");

但是不起作用,它(JComboBox)仍然响应SPACE键

对于我删除了SPACE印刷机效果的firstButton;我添加了键F,所以现在当你按下键盘上的F键时按下了firstButton,ant没有响应SPACE(意图).请注意,即使firstButton没有焦点,也会发生F的按下(JComponent.WHEN_IN_FOCUSED_WINDOW)

这是一个显示我的例子的SSCCE代码
注意:我故意没有将上面的代码添加到第二个按钮“secondButton”,因此它认仍然响应SPACE.

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();
            }
        });
    }
}

我想要控制JComponent的认击键的原因是因为我想在所有JComponent上删除SPACE的效果,除了一个按钮,它将响应SPACE按下,无论焦点在哪里,使用JComponent.WHEN_IN_FOCUSED_WINDOW,因此,单击另一个组件(并将焦点从例外按钮移开)将不会阻止SPACE对该按钮的影响.

另一点:如果您测试了上面的代码,您会注意到从JComboBox中选择一个项目会产生两行,如果您选择项目“4”,则JTextArea中的输出

06003

为什么两个?

谢谢.

解决方法

But doesn’t work,that it is (JComboBox) still respond to the SPACE
key

您应该像这样使用JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT InputMap(您可能会注意到我使用了KeyEvent和Keystroke.getKeystroke(int key,int modifier,boolean onRelease),因为它更易读,更不容易出错,即键入错误的字符串参数等.):

sizesComboBox.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
        .put(Keystroke.getKeystroke(KeyEvent.VK_SPACE,false),"none");

据我所知,其原因很好地解释了here

The component contains (or is) the component that has the focus. This
input map is commonly used for a composite component — a component
whose implementation depends on child components. For example,JTables
make all their bindings using WHEN_ANCESTOR_OF_FOCUSED_COMPONENT so
that if the user is editing,the up-arrow key (for example) still
changes the selected cell.

所以我推断JComboBox一个复合组件,因此我们需要正确的InputMap – WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,以删除其特定键的所有内部组件KeyBinding功能,即SPACE.

Another point: If you tested the code above,you will notice that
selecting an item from the JComboBox poduces two lines of,if you
select item “4” the output in the JTextArea is

06001

Why two??

正如@mKorbel所述(他的评论中有1条)可能会发生两件事:

>取消选择一个项目
>选择了一个项目

这些事件成对出现,就像我们选择新值时取消选择旧值一样.因此,我们必须检查并采取适当行动:

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

其他建议:

>不要在JFrame上调用setSize.>使用适当的LayoutManager和/或覆盖getPreferredSize以返回适合内容的Dimensions,并在设置可见之前和添加组件之后调用JFrame上的pack().

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...