繁体   English   中英

java swing键绑定 - 释放键的缺失操作

[英]java swing key bindings - missing action for released key

注册了“SPACE”和“已发布的SPACE”的键绑定,当空间是唯一按下/释放的键时,按照广告的方式工作,我注意到按下空格,然后按ctrl(或任何其他修改键),然后释放空间,最后释放ctrl将导致执行与“SPACE”关联的操作,但不会执行与“已释放的SPACE”关联的操作。

一旦不再按空格(或同时按下修改键),导致动作执行的首选方法是什么? 我只在Windows 7,64位上试过这个。

import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.AbstractAction;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
import java.awt.Cursor;

class Bind extends JPanel {
  {
    getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "pressed");
    getInputMap().put(KeyStroke.getKeyStroke("released SPACE"), "released");
    getActionMap().put("pressed", new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        System.out.println("pressed");
        setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); 
      }
    });
    getActionMap().put("released", new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        System.out.println("released");
        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
      }
    });
  }
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override public void run() {
        JFrame f = new JFrame("Key Bindings");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        f.add(new Bind());
        f.setSize(640, 480);
        f.setVisible(true);
      }
    });
  }
}

更新 :这是在释放空间之前意外点击ctrl,alt或shift时避免粘滞空间的方法:

import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.AbstractAction;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
import java.awt.Cursor;

class Bind extends JPanel {
  {
    getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "pressed");
    getInputMap().put(KeyStroke.getKeyStroke("released SPACE"), "released");
    getInputMap().put(KeyStroke.getKeyStroke("ctrl released SPACE"), "released");
    getInputMap().put(KeyStroke.getKeyStroke("shift released SPACE"), "released");
    getInputMap().put(KeyStroke.getKeyStroke("shift ctrl released SPACE"), "released");
    getInputMap().put(KeyStroke.getKeyStroke("alt released SPACE"), "released");
    getInputMap().put(KeyStroke.getKeyStroke("alt ctrl released SPACE"), "released");
    getInputMap().put(KeyStroke.getKeyStroke("alt shift released SPACE"), "released");
    getInputMap().put(KeyStroke.getKeyStroke("alt shift ctrl released SPACE"), "released");
    getActionMap().put("pressed", new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        System.out.println("pressed");
        setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); 
      }
    });
    getActionMap().put("released", new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        System.out.println("released");
        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
      }
    });
  }
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override public void run() {
        JFrame f = new JFrame("Key Bindings");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        f.add(new Bind());
        f.setSize(640, 480);
        f.setVisible(true);
      }
    });
  }
}

有意义的是,当Control键仍然按下时,不会触发released SPACE事件。 我希望control released SPACE事件被解雇。

将以下内容添加到您的代码中:

getInputMap().put(KeyStroke.getKeyStroke("control released SPACE"), "released");

出于同样的原因,如果您先按住Control键, SPACE事件将不会触发。 因此,您还需要为control SPACE添加绑定。

您需要对所有修改键执行此操作,这可能是也可能不是跟踪关键事件的简单解决方案。

您的操作系统可能不会触发keyReleased事件,而只会keyTyped keyPressedkeyTyped事件或其他组合,因此请先检查该事件。 您可能只需要检查keyTyped事件而不是keyReleased ,您将完成它。

简短回答:

使用位掩码或数组来跟踪当前处于“已按下”状态的键,然后使用那些值来触发事件。 也就是说,不要直接使用Swing事件来触发应用程序中的响应 - 您需要一个基本上存储键盘状态的额外层,并从该状态开始执行相关操作。

还有一些方法可用( 参见本教程结尾 - “isAltDown”,“isCtrlDown”等 )来检查当您收到按下“Space”键之类的事件时是否按下了修改键。

答案很长:

你按下并释放按键时会触发事件是正确的。 它必须以这种方式工作,以便您可以支持应该单独处理这些事件的应用程序,而不是一起处理。 一个例子(虽然这不是唯一一个)是PC上的视频游戏,你可能会同时按下多个字母/修改键(例如, A向左移动, W向前移动)游戏必须对待这两个事件作为不同的输入,而不是复合输入,导致你的前进 - 左移动。

所以,你基本上想做的事情,如果你需要处理复合输入,就有一个简单的应用程序需要响应的动作数组,以及它们相关的键绑定(无论是单键还是多键都不重要) )。 当按下某个键时,你基本上会打开该键的标志,表示它当前处于“按下”状态,并在释放时清除该标志。

然后,要触发您的事件,您只需检查所有按下的键(通过检查哪些键“标志”处于活动状态),如果按下特定事件的键组合,则触发事件。

如果你有少于32个触发事件的键,那么你实际上可以使用位掩码和32位int值,而不是数组。 事实上,如果可以的话,这样做会简单得多。 如果您需要多达64个密钥,请使用long执行相同的操作。 如果您触发事件的键很少(例如8或更少),则可以使用8位short类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM