如何知道用户何时真正发布了Java中的密钥?

Lui*_*iro 18 java swing keypress autorepeat keyrelease

(为清晰起见编辑)

我想检测用户何时按下并释放Java Swing中的键,忽略键盘自动重复功能.我还想在Linux,Mac OS和Windows上使用纯Java方法.

要求:

  1. 当用户按下某个键时,我想知道它是什么键;
  2. 当用户释放一些密钥时,我想知道它是什么密钥;
  3. 我想忽略系统自动重复选项:我希望每次按键只接收一个按键事件,每个按键释放只需一个按键释放事件;
  4. 如果可能的话,我会使用第1至第3项来知道用户是否一次持有多个键(即,她点击'a'并且没有释放它,她点击"Enter").

我在Java中面临的问题是,在Linux下,当用户持有一些密钥时,有许多keyPress和keyRelease事件被触发(因为键盘重复功能).

我尝试了一些没有成功的方法:

  1. 获取关键事件的最后一次发生 - 在Linux中,对于密钥重复它们似乎为零,但是,在Mac OS中它们不是;
  2. 仅当当前keyCode与最后一个keyCode不同时才考虑事件 - 这样用户不能连续两次击中相同的键;

这是代码的基本(非工作)部分:

import java.awt.event.KeyListener;

public class Example implements KeyListener {

public void keyTyped(KeyEvent e) {
}

public void keyPressed(KeyEvent e) {
    System.out.println("KeyPressed: "+e.getKeyCode()+", ts="+e.getWhen());
}

public void keyReleased(KeyEvent e) {
    System.out.println("KeyReleased: "+e.getKeyCode()+", ts="+e.getWhen());
}

}
Run Code Online (Sandbox Code Playgroud)

当用户持有密钥(即"p")时,系统显示:

KeyPressed:  80, ts=1253637271673
KeyReleased: 80, ts=1253637271923
KeyPressed:  80, ts=1253637271923
KeyReleased: 80, ts=1253637271956
KeyPressed:  80, ts=1253637271956
KeyReleased: 80, ts=1253637271990
KeyPressed:  80, ts=1253637271990
KeyReleased: 80, ts=1253637272023
KeyPressed:  80, ts=1253637272023
...
Run Code Online (Sandbox Code Playgroud)

至少在Linux下,JVM会在保持密钥时重新发送所有关键事件.为了使事情变得更加困难,在我的系统(Kubuntu 9.04 Core 2 Duo)上,时间戳不断变化.JVM使用相同的时间戳发送密钥新版本和新密钥.这使得很难知道密钥何时真正发布.

有任何想法吗?

谢谢

M1E*_*1EK 5

这可能有问题。我不记得了(已经很长时间了),但很可能重复键功能(由底层操作系统处理,而不是 Java)没有为 JVM 开发人员提供足够的信息来区分那些额外的来自“真实”事件的关键事件。(顺便说一下,我在 1.1.x 中的 OS/2 AWT 中处理过这个问题)。

来自 KeyEvent 的 javadoc:

“按键按下”和“按键释放”事件是较低级别的,取决于平台和键盘布局。每当按下或释放键时都会生成它们,并且是找出不生成字符输入的键(例如,操作键、修饰键等)的唯一方法。按下或释放的键由 getKeyCode 方法指示,该方法返回一个虚拟键代码。

我记得在 OS/2 中这样做(当时它仍然只有 2 事件向上/向下键盘处理的风格,就像旧版本的 Windows,而不是你在更多的 3 事件向上/向下/字符风格现代版本),如果只是按住键并且事件自动生成,我不会以任何不同的方式报告 KeyReleased 事件;但我怀疑 OS/2 甚至没有向我报告该信息(记不清了)。我们使用来自 Sun 的 Windows 参考 JVM 作为我们开发 AWT 的指南 - 所以我怀疑是否可以在那里报告这些信息,我至少会在他们的最后看到它。


luv*_*ere 0

好吧,你说在按键重复的情况下按键事件之间的时间可能是非负的。即便如此,它也可能很短。然后,您可以将此时间阈值设置为某个非常小的值,并且等于或低于该值的所有内容都被视为关键重复。