Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在JTextField中点击空格键会触发父窗口的键绑定_Java_Swing_Key Bindings - Fatal编程技术网

Java 在JTextField中点击空格键会触发父窗口的键绑定

Java 在JTextField中点击空格键会触发父窗口的键绑定,java,swing,key-bindings,Java,Swing,Key Bindings,我在JFrame的根窗格中注册了一个事件,该事件在按下空格键时发生反应(打开另一个窗口)。我在JFrame中还有一个JTextField。当用户处于my textfield的编辑模式并点击空格键时,空格事件应该仅由textfield使用,而不是转发到JFrame的actionmap 我该怎么做 以下是该问题的可运行演示: import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.Key

我在
JFrame
的根窗格中注册了一个事件,该事件在按下空格键时发生反应(打开另一个窗口)。我在JFrame中还有一个
JTextField
。当用户处于my textfield的编辑模式并点击空格键时,空格事件应该仅由textfield使用,而不是转发到
JFrame
的actionmap

我该怎么做

以下是该问题的可运行演示:

import java.awt.FlowLayout;
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.JLabel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;

public class TestDialog {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "spaceAction");
        frame.getRootPane().getActionMap().put("spaceAction", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("spaceAction");
            }
        });
        JTextField tf = new JTextField("textfield");
        JLabel label = new JLabel("otherComponent");
        label.setFocusable(true);
        frame.getContentPane().setLayout(new FlowLayout());
        frame.getContentPane().add(tf);
        frame.getContentPane().add(label);
        frame.pack();
        frame.setVisible(true);

    }

}

使用空格键作为全局触发器不是一个好主意。但如果你真的需要它,这里有一个方法:

import java.awt.EventQueue;
import java.awt.FlowLayout;
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.JLabel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.text.JTextComponent;

public class DialogTest {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "spaceAction");
        frame.getRootPane().getActionMap().put("spaceAction", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (EventQueue.getCurrentEvent() instanceof KeyEvent) {
                    KeyEvent ke = (KeyEvent) EventQueue.getCurrentEvent();
                    if (!(ke.getComponent() instanceof JTextComponent)) {
                        System.out.println("spaceAction");
                    } else {
                        System.out.println("Ignore event in text component");
                    }
                } else {
                    System.out.println("spaceAction");
                }
            }
        });
        JTextField tf = new JTextField("textfield");
        JLabel label = new JLabel("otherComponent");
        label.setFocusable(true);
        frame.getContentPane().setLayout(new FlowLayout());
        frame.getContentPane().add(tf);
        frame.getContentPane().add(label);
        frame.pack();
        frame.setVisible(true);

    }

}
更好的方法是从根窗格开始遍历组件树,并仅为您需要的组件(例如所有标签)添加键绑定。这是我的遍历方法

/**
 * Searches for all children of the given component which are instances of the given class.
 *
 * @param aRoot start object for search.
 * @param aClass class to search.
 * @param <E> class of component.
 * @return list of all children of the given component which are instances of the given class. Never null.
 */
public static <E> List<E> getAllChildrenOfClass(Container aRoot, Class<E> aClass) {
    final List<E> result = new ArrayList<E>();
    final Component[] children = aRoot.getComponents();
    for (final Component c : children) {
        if (aClass.isInstance(c)) {
            result.add(aClass.cast(c));
        }
        if (c instanceof Container) {
            result.addAll(getAllChildrenOfClass((Container) c, aClass));
        }
    }
    return result;
}
/**
*搜索作为给定类实例的给定组件的所有子级。
*
*@param aRoot开始搜索对象。
*@param aClass类进行搜索。
*@param组件的类。
*@返回给定组件的所有子级的列表,这些子级是给定类的实例。永不为空。
*/
公共静态列表getAllChildrenOfClass(容器aRoot,类aClass){
最终列表结果=新建ArrayList();
final Component[]children=aRoot.getComponents();
用于(最终部分c:儿童){
if(类I实例(c)){
结果.添加(类铸件(c));
}
if(容器的c实例){
结果.addAll(getAllChildrenOfClass((容器)c,aClass));
}
}
返回结果;
}

我通过创建一个简单的JTextField子类解决了这个问题,该子类使用用户按下的所有可打印字符。这样,您就不必修改封闭组件

public class JTextFieldNoKeyBinding extends JTextField
{

    public JTextFieldNoKeyBinding()
    {
        // Key presses are processed by JTextField but NOT consumed,
        // so they end up being also processed by the key binding framework.
        // The only way to block them is to capture all the printable keys: see
        // https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html
        for (char c = 32; c <= 126; c++)
        {
            getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(c, 0), "doNothing");
            getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(c, InputEvent.SHIFT_DOWN_MASK), "doNothing");
        }
        getActionMap().put("doNothing", new NoAction());
    }

    private class NoAction extends AbstractAction
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            //do nothing
        }
    }
}
公共类JTextFieldNoKeyBinding扩展了JTextField
{
公共JTextFieldNoKeyBinding()
{
//按键由JTextField处理,但不使用,
//因此,它们最终也被密钥绑定框架处理。
//阻止它们的唯一方法是捕获所有可打印的键:请参阅
// https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html

对于(char c=32;c)你使用了什么输入映射级别?也许考虑提供一个可运行的例子来演示你的问题。我尝试了所有3个输入映射级别,它们都在按预期的方式工作(PosirOrthoFixCuxSeMeCopp,当你在FixSuxy窗口,当聚焦时),前两个功能如我所述正常工作,第三个级别根本不起作用,因为根窗格没有焦点,我不应该使用您的第一个解决方案解决它,谢谢。但这是一个功能还是一个JTextField转发已使用的键盘字符的bug?@trainRobble我认为这是一个功能。在某些情况下,是多事件可能需要进行处理。