Java 即使选择了JTextField,箭头键键绑定仍然有效

Java 即使选择了JTextField,箭头键键绑定仍然有效,java,swing,focus,jtextfield,key-bindings,Java,Swing,Focus,Jtextfield,Key Bindings,我正在使用键绑定,并在聚焦窗口中使用条件WHEN,以便键始终工作。然而,如果选择了JTextField,则箭头键(左、右、上、下)键绑定似乎会停止工作 简单地说,我希望无论JComponent的焦点是什么,键绑定都能始终工作 import java.awt.Dimension; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java

我正在使用键绑定,并在聚焦窗口中使用条件WHEN,以便键始终工作。然而,如果选择了JTextField,则箭头键(左、右、上、下)键绑定似乎会停止工作

简单地说,我希望无论JComponent的焦点是什么,键绑定都能始终工作

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.WindowConstants;

public class Test extends JPanel implements ActionListener {
    private static final long serialVersionUID = 1L;

    private static JTextField field;

    private static JFrame frame;

    private static boolean up = false, down = false, left = false, right = false;

    private static int x = 275, y = 275;

    public static void main(String[] args) {
        Test t = new Test();
        t.setBounds(0, 0, 1200, 600);
        t.setVisible(true);

        field = new JTextField();
        field.setBounds(20, 20, 100, 20);

        Timer repaintTimer = new Timer(2, t);

        frame = new JFrame();
        frame.setSize(600, 600);

        setUpKeyActions(t);

        frame.add(field);
        frame.add(t);

        Dimension dim = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setLocation((dim.width - frame.getWidth()) / 2, (dim.height - frame.getHeight()) / 2);
        frame.getContentPane().setLayout(null);
        frame.setAlwaysOnTop(true);
        frame.setResizable(false);

        repaintTimer.start();

        frame.setVisible(true);
        frame.requestFocus();
    }

    private static void setUpKeyActions(Test t) {
        int condition = WHEN_IN_FOCUSED_WINDOW;

        new KeyAction(t, condition, KeyEvent.VK_UP, 0, false) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                up = true;
            }

        };

        new KeyAction(t, condition, KeyEvent.VK_UP, 0, true) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                up = false;
            }

        };

        new KeyAction(t, condition, KeyEvent.VK_LEFT, 0, false) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                left = true;
            }

        };

        new KeyAction(t, condition, KeyEvent.VK_LEFT, 0, true) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                left = false;
            }

        };

        new KeyAction(t, condition, KeyEvent.VK_RIGHT, 0, false) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                right = true;
            }

        };

        new KeyAction(t, condition, KeyEvent.VK_RIGHT, 0, true) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                right = false;
            }

        };

        new KeyAction(t, condition, KeyEvent.VK_DOWN, 0, false) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                down = true;
            }

        };

        new KeyAction(t, condition, KeyEvent.VK_DOWN, 0, true) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                down = false;
            }

        };

    }

    private static abstract class KeyAction extends AbstractAction {
        private static final long serialVersionUID = 1L;

        KeyAction(JComponent component, int condition, int keyCode, int modifiers, boolean onKeyRelease) {
            InputMap inputMap = component.getInputMap(condition);
            ActionMap actionMap = component.getActionMap();
            KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, modifiers, onKeyRelease);
            inputMap.put(keyStroke, keyStroke.toString());
            actionMap.put(keyStroke.toString(), this);
        }

    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if(up)
            y -= 1;
        if(down)
            y += 1;
        if(right)
            x += 1;
        if(left)
            x -= 1;
        if(x < 0)
            x = 0;
        else if(x > frame.getWidth() - 30)
            x = frame.getWidth() - 30;
        if(y < 0)
            y = 0;
        else if(y > frame.getHeight() - 50)
            y = frame.getHeight() - 50;
        g.drawRect(x, y, 30, 30);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        frame.repaint();
    }

}
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.KeyEvent;
导入javax.swing.AbstractAction;
导入javax.swing.ActionMap;
导入javax.swing.InputMap;
导入javax.swing.JComponent;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JTextField;
导入javax.swing.KeyStroke;
导入javax.swing.Timer;
导入javax.swing.WindowConstants;
公共类测试扩展JPanel实现ActionListener{
私有静态最终长serialVersionUID=1L;
私有静态JTextField字段;
私有静态JFrame;
私有静态布尔值up=false,down=false,left=false,right=false;
私有静态int x=275,y=275;
公共静态void main(字符串[]args){
测试t=新测试();
t、 立根(0,0,1200,600);
t、 setVisible(真);
field=新的JTextField();
场地.立根(20,20,100,20);
定时器重新绘制定时器=新定时器(2,t);
frame=新的JFrame();
框架。设置尺寸(600600);
关键动作(t);
帧。添加(字段);
帧。添加(t);
维度dim=java.awt.Toolkit.getDefaultToolkit().getScreenSize();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLocation((dim.width-frame.getWidth())/2,(dim.height-frame.getHeight())/2);
frame.getContentPane().setLayout(null);
frame.setAlwaysOnTop(真);
frame.setresizeable(false);
repaittimer.start();
frame.setVisible(true);
frame.requestFocus();
}
专用静态无效设置键动作(测试t){
int condition=当在聚焦窗口中时;
新的KeyAction(t,条件,KeyEvent.VK_UP,0,false){
私有静态最终长serialVersionUID=1L;
@凌驾
已执行的公共无效操作(操作事件e){
向上=真;
}
};
新的KeyAction(t,条件,KeyEvent.VK_UP,0,真){
私有静态最终长serialVersionUID=1L;
@凌驾
已执行的公共无效操作(操作事件e){
向上=错误;
}
};
新的KeyAction(t,条件,KeyEvent.VK_左,0,假){
私有静态最终长serialVersionUID=1L;
@凌驾
已执行的公共无效操作(操作事件e){
左=真;
}
};
新的KeyAction(t,条件,KeyEvent.VK_左,0,真){
私有静态最终长serialVersionUID=1L;
@凌驾
已执行的公共无效操作(操作事件e){
左=假;
}
};
新的KeyAction(t,条件,KeyEvent.VK_RIGHT,0,false){
私有静态最终长serialVersionUID=1L;
@凌驾
已执行的公共无效操作(操作事件e){
右=真;
}
};
新的KeyAction(t,条件,KeyEvent.VK_RIGHT,0,true){
私有静态最终长serialVersionUID=1L;
@凌驾
已执行的公共无效操作(操作事件e){
右=假;
}
};
新的按键动作(t,条件,KeyEvent.VK_向下,0,错误){
私有静态最终长serialVersionUID=1L;
@凌驾
已执行的公共无效操作(操作事件e){
向下=真;
}
};
新键动作(t,条件,KeyEvent.VK_向下,0,真){
私有静态最终长serialVersionUID=1L;
@凌驾
已执行的公共无效操作(操作事件e){
向下=假;
}
};
}
私有静态抽象类KeyAction扩展了AbstractAction{
私有静态最终长serialVersionUID=1L;
KeyAction(JComponent组件、int条件、int键代码、int修饰符、布尔onKeyRelease){
InputMap InputMap=component.getInputMap(条件);
ActionMap ActionMap=component.getActionMap();
击键击键=击键。getKeyStroke(键代码、修改器、onKeyRelease);
inputMap.put(击键,击键.toString());
actionMap.put(keyStroke.toString(),this);
}
}
@凌驾
公共组件(图形g){
超级组件(g);
如果(向上)
y-=1;
如果(向下)
y+=1;
如果(右)
x+=1;
如果(左)
x-=1;
if(x<0)
x=0;
else if(x>frame.getWidth()-30)
x=frame.getWidth()-30;
if(y<0)
y=0;
否则,如果(y>frame.getHeight()-50)
y=frame.getHeight()-50;
g、 drawRect(x,y,30,30);
}
@凌驾
已执行的公共无效操作(操作事件e){
frame.repaint();
}
}
在上面的代码中,框随箭头键移动。但是,如果选择左上角的文本框,该框将不再移动

更新:

我试图将键绑定添加到JTextFields中,正如@camickr给出的答案所示,但它似乎不起作用。也许我做错了什么

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.WindowConstants;

public class Test extends JPanel implements ActionListener {
    private static final long serialVersionUID = 1L;

    private static JFrame frame;

    private static boolean up = false, down = false, left = false, right = false;

    private static int x = 275, y = 275;

    public static void main(String[] args) {
        Test t = new Test();
        t.setBounds(0, 0, 1200, 600);
        t.setVisible(true);

        JTextField field = new JTextField();
        field.setBounds(20, 20, 100, 20);

        Timer repaintTimer = new Timer(2, t);

        frame = new JFrame();
        frame.setSize(600, 600);

        setUpKeyActions(t, field);

        frame.add(field);
        frame.add(t);

        Dimension dim = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setLocation((dim.width - frame.getWidth()) / 2, (dim.height - frame.getHeight()) / 2);
        frame.getContentPane().setLayout(null);
        frame.setAlwaysOnTop(true);
        frame.setResizable(false);

        repaintTimer.start();

        frame.setVisible(true);
        frame.requestFocus();
    }

    private static void setUpKeyActions(Test t, JTextField field) {
        int condition = WHEN_IN_FOCUSED_WINDOW;

        new KeyAction(condition, KeyEvent.VK_UP, 0, false, t, field) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                up = true;
            }

        };

        new KeyAction(condition, KeyEvent.VK_UP, 0, true, t, field) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                up = false;
            }

        };

        new KeyAction(condition, KeyEvent.VK_LEFT, 0, false, t, field) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                left = true;
            }

        };

        new KeyAction(condition, KeyEvent.VK_LEFT, 0, true, t, field) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                left = false;
            }

        };

        new KeyAction(condition, KeyEvent.VK_RIGHT, 0, false, t, field) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                right = true;
            }

        };

        new KeyAction(condition, KeyEvent.VK_RIGHT, 0, true, t, field) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                right = false;
            }

        };

        new KeyAction(condition, KeyEvent.VK_DOWN, 0, false, t, field) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                down = true;
            }

        };

        new KeyAction(condition, KeyEvent.VK_DOWN, 0, true, t, field) {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                down = false;
            }

        };

    }

    private static abstract class KeyAction extends AbstractAction {
        private static final long serialVersionUID = 1L;

        KeyAction(int condition, int keyCode, int modifiers, boolean onKeyRelease, JComponent component, JComponent... components) {
            InputMap inputMap = component.getInputMap(condition);
            ActionMap actionMap = component.getActionMap();
            KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, modifiers, onKeyRelease);
            inputMap.put(keyStroke, keyStroke.toString());
            actionMap.put(keyStroke.toString(), this);
            for(JComponent jc : components) {
                inputMap = jc.getInputMap(condition);
                actionMap = jc.getActionMap();
                keyStroke = KeyStroke.getKeyStroke(keyCode, modifiers, onKeyRelease);
                inputMap.put(keyStroke, keyStroke.toString());
                actionMap.put(keyStroke.toString(), this);
            }
        }

    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if(up)
            y -= 1;
        if(down)
            y += 1;
        if(right)
            x += 1;
        if(left)
            x -= 1;
        if(x < 0)
            x = 0;
        else if(x > frame.getWidth() - 30)
            x = frame.getWidth() - 30;
        if(y < 0)
            y = 0;
        else if(y > frame.getHeight() - 50)
            y = frame.getHeight() - 50;
        g.drawRect(x, y, 30, 30);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        frame.repaint();
    }

}
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.KeyEvent;
导入javax.swing.AbstractAction;
导入javax.swing.Act
InputMap im = (InputMap)UIManager.get("TextField.focusInputMap");
KeyStroke keyStroke = KeyStroke.getKeyStroke("RIGHT");
im.put(keyStroke, "none"); //noop
ActionMap am = (ActionMap)UIManager.get("TextField.actionMap");
am.put("caret-forward", yourRightActionHere);