某些关键事件组合未触发

时间:2015-02-02 02:25:46

标签: java key-bindings

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

我将提供有关键绑定的游戏机制的一些背景信息。在这个二维游戏中,你的角色可以通过按住非小键盘箭头键组合(向上,向左和向下+向右分别为北,东和西南方向)以恒定速度在所有八个方向上移动。 )您也可以按住Shift键并结合之前提到的任何键组合,以相同的方向移动,但速度较慢。

以下是遇到此问题的程序示例的代码。这个例子中的问题与相对较大的子弹地狱计划中的问题相同。

/*
 * 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");
        }
    }
}

如果您按下几秒钟然后释放它,程序将触发许多按下的事件,然后是一个向上发布的事件。在游戏中,这将以标准速度向上移动。

如果按下shift键,然后向上按几秒钟,然后松开,程序将触发许多升档按下的事件,然后发布升档事件。必须首先按下Shift键,然后最后释放(如果你完全释放它),这样才能工作。在游戏中,这将以较慢的速度向上移动。

如果你按下shift,然后向上按几秒钟,然后释放换档,然后在释放换档后释放几秒钟,程序将首先发出大量按下升档的事件,然后启动按下的事件,最后发布了一个已发布的事件。在游戏中,这将以较慢的速度向上移动,然后决定以更快的速度向上移动。

如果你按下几秒钟,然后按下shift键,程序将首先发出大量按下的事件,然后在按住shift键时不发出任何事件。预期的行为是,一旦在按下时按下它,它应该开始触发向上移动的按下事件而不是向上按下的事件。如果玩家以标准速度向上移动,然后想要以较慢的速度移动,这将适用于游戏中 继续前一个场景:
如果你在按下的同时释放换档,尽管你现在只是按下它,它不会发出任何向上按下的事件。如果你现在释放它,它仍然会触发一个向上释放的事件,即使它永远不会触发任何压制事件 如果你在仍然保持换档的情况下释放,它将触发一次升级释放事件,即使它永远不会触发任何升档压力事件。

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

现在问一下,有没有办法绕过操作系统的关键事件处理,以便在按住时按下shift会触发向上移动的按下事件?

0 个答案:

没有答案