由于失去焦点,键绑定会随机停止工作吗?

时间:2016-11-05 13:23:07

标签: java swing keyboard keylistener key-bindings

我知道我之前发过关于这个主题的问题,但我在这里发布了一个新问题,因为我创建了我需要的MCVE。这是可以重现问题的类(如果您将此代码复制并粘贴到Java编辑器中(但更改包名称),那么它将能够成功启动而不会出现问题。这是一个完整的测试程序):

package com.blockhead7360.test.ppa;

import java.awt.Dimension;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;

public class TotalKeyTest {

static JTextArea area;

static int i = 0;

public TotalKeyTest(){
    JFrame frame = new JFrame("Test");
    frame.setPreferredSize(new Dimension(600, 600));
    frame.setMaximumSize(new Dimension(600, 600));
    frame.setMinimumSize(new Dimension(600, 600));

    JComponent comp = (JComponent) frame.getContentPane();
    frame.getRootPane().getRootPane().setActionMap(bindKeys(comp).getActionMap());
    frame.getRootPane().getRootPane().setInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW, bindKeys(comp).getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW));
    frame.pack();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setResizable(false);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);         

}

public static JComponent bindKeys(JComponent comp){
    comp.getInputMap().put(KeyStroke.getKeyStroke("pressed SPACE"), "pressSpace");
    comp.getActionMap().put("pressSpace", new AbstractAction(){

        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e){
            System.out.println("pressed Space");
        }
    });

    comp.getInputMap().put(KeyStroke.getKeyStroke("pressed A"), "pressLeft");
    comp.getActionMap().put("pressLeft", new AbstractAction(){

        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e){
            System.out.println("pressed left");
        }
    });
    comp.getInputMap().put(KeyStroke.getKeyStroke("released A"), "releaseLeft");
    comp.getActionMap().put("releaseLeft", new AbstractAction(){

        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e){
            System.out.println("released left");
        }
    });

    comp.getInputMap().put(KeyStroke.getKeyStroke("D"), "pressRight");
    comp.getActionMap().put("pressRight", new AbstractAction(){

        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e){
            System.out.println("pressed right");
        }
    });
    comp.getInputMap().put(KeyStroke.getKeyStroke("released D"), "releaseRight");
    comp.getActionMap().put("releaseRight", new AbstractAction(){

        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e){
            System.out.println("released right");
        }
    });
    return comp;

}

public static void main(String args[]){
    new TotalKeyTest();
}

}

如果您希望将其作为pastebin,那么它是:http://pastebin.com/EhPJeAPC

基本上,当我在开始时按下SPACE,A和D键几次(短按和长按)时,它会起作用。经过短暂和长时间的压力后,它就停止工作了!

有人可以帮忙吗?

编辑:BTW我知道代码包含了frame.getRootPane(),而不仅仅是使用frame.add(),但这就是因为我正在尝试一些东西。如果你愿意,我可以改回来。

编辑:我发现如果我使用箭头键而不是A和D键,它的工作完全正常。我不知道为什么,但我会用它滚动。

1 个答案:

答案 0 :(得分:1)

您正在为contentPane获取错误的输入映射。您应该使用默认getInputMap()使用默认JComponent.WHEN_FOCUSED地图,当您应该使用更具体的getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)

例如,我的MCVE:

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

import javax.swing.*;

@SuppressWarnings("serial")
public class TotalKeyTest2 extends JPanel {
    private static final int PREF_W = 600;
    private static final int PREF_H = PREF_W;
    private int condition = WHEN_IN_FOCUSED_WINDOW;
    private InputMap inputMap = getInputMap(condition);
    private ActionMap actionMap = getActionMap();

    public TotalKeyTest2() {
        setBindings();
    }

    private void setBindings() {        
        insertKey(KeyEvent.VK_SPACE, "Space");
        insertKey(KeyEvent.VK_A, "Left");
        insertKey(KeyEvent.VK_D, "Right");
    }

    private void insertKey(int keyCode, String text) {
        KeyStroke pressed = KeyStroke.getKeyStroke(keyCode, 0, false);
        KeyStroke released = KeyStroke.getKeyStroke(keyCode, 0, true);
        String pressedActionName = text + " Pressed";
        String releasedActionName = text + " Released";
        Action pressedAction = new MyAction(pressedActionName);
        Action releasedAction = new MyAction(releasedActionName);        
        inputMap.put(pressed, pressedActionName);
        inputMap.put(released, releasedActionName);
        actionMap.put(pressedActionName, pressedAction);
        actionMap.put(releasedActionName, releasedAction);
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    private class MyAction extends AbstractAction {

        public MyAction(String name) {
            super(name);
        }


        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println(getValue(NAME));
        }
    }

    private static void createAndShowGui() {
        TotalKeyTest2 mainPanel = new TotalKeyTest2();

        JFrame frame = new JFrame("TotalKeyTest2");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}