Java:如何从任何JComponent中删除默认的KeyStrokes? [英] Java: How to remove default KeyStrokes from any JComponent?

查看:96
本文介绍了Java:如何从任何JComponent中删除默认的KeyStrokes?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想控制哪个按键属于哪个Jcomponent.我什至想了解如何删除与Jcomponent关联的默认按键并将其替换为其他喜欢的按键.

I want to control which keystroke belong to which Jcomponent. I even want to get how to remove the default keystrokes associated with a Jcomponent and replace them with other favourite keystrokes.

我遵循了这个oracle 教程,给出了JButton的示例,我尝试了它并且工作正常,但是当我使用

I followed this oracle tutorial, it gives an example with JButton, I tried it and it works fine, but when I try it with JComboBox it doesn’t work!

我尝试删除的是 SPACE 键,这是防止JComponent响应 SPACE 按下的键

What exactly I tried is removing the SPACE key, that is prevent the JComponent from responding to SPACE presses

我使用以下代码删除了 SPACE 键:

I used this code to remove the SPACE key:

firstButton.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "none");

JComboBox也是如此

The same thing for JComboBox

sizesComboBox.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "none");

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

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

对于我删除了 SPACE 印刷机效果的firstButton;我添加了键 F ,因此,当您按键盘上的 F 键时,现在按下了firstButton,蚂蚁不响应 SPACE (预期).请注意,即使firstButton没有焦点(JComponent.WHEN_IN_FOCUSED_WINDOW)

For the firstButton that I removed the effect of SPACE presses; I added the key F, So that now the firstButton is pressed when you press the F key on the keyboard, ant not respond to SPACE (intended). Note that presses of F take place even if firstButton doesn’t have the focus (JComponent.WHEN_IN_FOCUSED_WINDOW)

这是一个显示我的示例的SSCCE代码:
注意:我故意没有将上面的代码行添加到第二个按钮"secondButton",因此默认情况下它仍会响应 SPACE .

This is a SSCCE code showing my example:
Note: I intentionally didn’t add the line of code above to the second button "secondButton" so it is still respond to SPACE by default.

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 的默认效果,除了一个按钮,它将使用JComponent.WHEN_IN_FOCUSED_WINDOW响应 SPACE 的按下(无论焦点位于何处),以便单击另一个组件(将焦点从例外按钮移开)不会阻止 SPACE的效果上的按钮.

The reason why I want to control over default keystrokes for JComponent is because I want to remove the default effect of SPACE on all the JComponent, except one button that will respond to the SPACE presses, wherever the focus is on, using JComponent.WHEN_IN_FOCUSED_WINDOW, so that clicking another component (and moving the focus away from the excepted button) will not prevent the effect of SPACE on that button.

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

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

Item 4
Item 4

为什么要两个?

谢谢.

推荐答案

但是不起作用,因为它是(JComboBox)仍对SPACE做出响应 键

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

您应该像这样使用JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT InputMap(您可能会注意到,我使用KeyEventKeyStroke.getKeyStroke(int key,int modifier,boolean onRelease)作为其更易读且不易出错的错误,例如,键入错误的字符串参数等):

You should use the JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT InputMap like so (As you may notice I make use of KeyEvent and KeyStroke.getKeyStroke(int key,int modifier,boolean onRelease) as its more readable and less prone to mistakes i.e typing the wrong string argument etc.):

sizesComboBox.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
        .put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,0,false), "none");

据我所知,这样做的原因很好地解释了这里:

The reason for this as far as I see is explained nicely here:

该组件包含(或是)具有焦点的组件.这 输入映射通常用于复合组件-组件 其实现取决于子组件.例如,JTable s 使用WHEN_ANCESTOR_OF_FOCUSED_COMPONENT进行所有绑定,因此 如果用户正在编辑,则向上箭头键(例如) 更改选定的单元格.

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,以删除特定键(例如 SPACE )的所有内部组件KeyBinding功能. /p>

So I deduce JCombobox is a composite component and thus we need the correct InputMap - WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, to remove all its inner components KeyBinding functionality for a specific key i.e SPACE.

另一点:如果您测试了上面的代码,您会注意到 如果您从JComboBox中选择一项,则会出现两行 选择项目"4",在JTextArea中的输出是

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

Item 4
Item 4

为什么要两个?

如@mKorbel所说(他的评论+1),可能发生2个事件:

As said by @mKorbel (+1 to his comment) there are 2 events which can occur:

  • 取消选择了一个项目
  • 已选择一个项目

这些事件成对发生,因为当我们选择一个新值时会取消选择旧值.因此,我们必须对此进行检查并采取适当的行动:

These events, occur in pairs as when we select a new value the old one is deselected. Thus we must check for this and act appropriately:

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

其他建议

  • 不要在JFrame上呼叫setSize.

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

Use an appropriate LayoutManager and/or override getPreferredSize to return Dimensions which fit the contents and call pack() on JFrame before setting is visible and after adding components.

这篇关于Java:如何从任何JComponent中删除默认的KeyStrokes?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆