Java 某些关键事件组合不触发

Java 某些关键事件组合不触发,java,key-bindings,Java,Key Bindings,在创建一个简单的子弹地狱游戏时,我遇到了一个键绑定问题 我将提供一些与键绑定相关的游戏机制的背景信息。在这个二维游戏中,您的角色可以在所有八个方向上以恒定的速度移动,方法是分别按住北、东和西南方向的上、左、下+右箭头组合键。您还可以按住shift键并结合前面提到的任意组合键,以相同的方向移动,但速度较慢 下面是遇到此问题的程序示例的代码。本例中的问题与相对较大的bullet hell程序中的问题相同 /* * Keybind feedback, by Nematodes */ import

在创建一个简单的子弹地狱游戏时,我遇到了一个键绑定问题

我将提供一些与键绑定相关的游戏机制的背景信息。在这个二维游戏中,您的角色可以在所有八个方向上以恒定的速度移动,方法是分别按住北、东和西南方向的上、左、下+右箭头组合键。您还可以按住shift键并结合前面提到的任意组合键,以相同的方向移动,但速度较慢

下面是遇到此问题的程序示例的代码。本例中的问题与相对较大的bullet hell程序中的问题相同

/*
 * Keybind feedback, by Nematodes
 */

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

public class keybindFeedback extends JFrame
{
    private static final long serialVersionUID = 0L;
    JPanel framePanel = new JPanel();
    private static Action moveUpTrue;
    private static Action moveUpFalse;
    private static Action moveUpFocusedTrue;
    private static Action moveUpFocusedFalse;

    public static void main(String[] args)
    {
        keybindFeedback createFrame = new keybindFeedback();
        createFrame.constructFrame();
    }

    public void constructFrame()
    {
        // Construct the frame and frame components
        setTitle("Keybind Feedback");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        getContentPane().setLayout(new GridBagLayout());
        setVisible(true);

        GridBagConstraints gridConstraints;

        // This JPanel only exists so that it is easier to focus on the window, so that keyevents will register
        gridConstraints = new GridBagConstraints();
        gridConstraints.gridx = 0;
        gridConstraints.gridy = 0;
        framePanel.setBackground(Color.BLACK);
        framePanel.setPreferredSize(new Dimension(700, 700));
        getContentPane().add(framePanel, gridConstraints);

        pack();

        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((int) (0.5 * (screenSize.width - getWidth())),
                 (int) (0.5 * (screenSize.height - getHeight())), getWidth(), getHeight());

        // Initialize and map all of the keybinds
        moveUpTrue = new MoveUpTrue();
        moveUpFalse = new MoveUpFalse();
        moveUpFocusedTrue = new MoveUpFocusedTrue();
        moveUpFocusedFalse = new MoveUpFocusedFalse();

        // Code spacing for placing things in the input map is only wonky in this code-formatting block due to strange spacing issues in stackoverflow
        framePanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("UP"), "doMoveUpTrue");

        framePanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released UP"), "doMoveUpFalse");
        framePanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("shift UP"), "doMoveUpFocusedTrue");

        framePanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("shift released UP"), "doMoveUpFocusedFalse");

        framePanel.getActionMap().put("doMoveUpTrue", moveUpTrue);
        framePanel.getActionMap().put("doMoveUpFalse", moveUpFalse);
        framePanel.getActionMap().put("doMoveUpFocusedTrue", moveUpFocusedTrue);
        framePanel.getActionMap().put("doMoveUpFocusedFalse", moveUpFocusedFalse);
    }

    // Keybind actions for up, up released, shift-up, and shift-up released
    class MoveUpTrue extends AbstractAction
    {
        public void actionPerformed(ActionEvent e)
        {
            System.out.println("Up");
        }
    }

    class MoveUpFalse extends AbstractAction
    {
        public void actionPerformed(ActionEvent e)
        {
            System.out.println("Up released");
        }
    }

    class MoveUpFocusedTrue extends AbstractAction
    {
        public void actionPerformed(ActionEvent e)
        {
            System.out.println("Shift-up");
        }
    }

    class MoveUpFocusedFalse extends AbstractAction
    {
        public void actionPerformed(ActionEvent e)
        {
            System.out.println("Shift-up released");
        }
    }
}
如果您按住up键几秒钟,然后将其释放,程序将触发大量向上按下的事件,然后触发向上释放的事件。在游戏中,这将以标准速度向上移动

如果按shift,然后按up几秒钟,然后释放up,程序将触发大量按下shift up的事件,然后触发一个按下shift up的释放事件。必须先按下Shift键,如果要使其工作,则必须最后松开Shift键。在游戏中,这将以较慢的速度向上移动

如果按shift,然后按up几秒钟,然后释放shift,然后在释放shift几秒钟后释放up,程序将首先触发大量按下shift的事件,然后触发按下的事件,最后触发一个向上释放的事件。在游戏中,这将是以较慢的速度向上移动,然后决定以较快的速度向上移动

如果您按up几秒钟,然后按shift,程序将首先触发大量向上按下的事件,然后在按住shift时不触发任何事件。预期的行为是,在按住shift键的同时按下shift键,它应该开始触发shift up pressed事件,而不是up pressed事件。如果玩家以标准速度向上移动,然后想要以较慢的速度移动,这将适用于游戏中。 从上一个场景继续: 如果您在按住shift键的同时释放shift键,则尽管您现在只按下了up键,但它不会触发任何up-pressed事件。如果您现在释放up,它仍然会触发up-released事件,即使它永远不会触发任何up-pressed事件。 如果您在按住shift键的同时释放up,它将触发一个shift up released事件,即使它从未触发任何按下shift up键的事件

这不是我键盘上的键翻转问题,因为它可以组合按下所有这些键。 这不是java不接受关键事件的问题。 这是我使用的Windows 7操作系统的自然行为,这恰好是有问题的。在普通文本框中使用shift键和字母键时,也会看到相同的行为


现在问一下,有没有办法绕过操作系统的按键事件处理,以便按住shift键的同时按下shift键将触发shift-up按下事件?

根据我的有限测试,除非在按住shift键之前按下shift键,否则shift+up绑定将不会触发…另请参阅。