有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java某些键-事件组合未触发

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

我将提供一些与键绑定相关的游戏机制的背景信息。在这个二维游戏中,您的角色可以通过按住非numpad箭头组合(分别为北、东和西南方向的上、左和下+右)以恒定速度在所有八个方向移动您还可以按住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不接受关键事件的问题
这是Windows7(我正在使用的操作系统)的自然行为,这恰好是有问题的。在普通文本框中使用shift键和字母键时,也会看到相同的行为

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


共 (0) 个答案