gpt4 book ai didi

java - 跳过 Java KeyEvents

转载 作者:行者123 更新时间:2023-12-04 06:38:23 26 4
gpt4 key购买 nike

我有一个程序,用户可以在其中按一个键来执行操作。那个事件需要很少的时间。用户还可以按住该键并连续多次执行该操作。问题是 keyPress() 事件排队的速度比处理事件的速度要快。这意味着在用户释放键后,事件继续得到处理,这些事件从用户之前按住键的队列中排队。我还注意到 keyRelease 事件直到最后的 keyPress 事件被处理后才会发生,而不管该键何时被真正释放。我希望能够
1. 检测按键释放事件并忽略以后的 keyPress 事件,直到用户实际再次按下按键。
2. 不执行后续的 keyPress 事件,直到第一个完成,然后检测何时没有按下该键,然后停止。

有谁知道如何做到这一点?

最佳答案

免责声明 : 我感觉不舒服所以这段代码很可怕,好像……它也很恶心。

我想要发生的事情 :访问 DirectInput 以获取键盘状态,而不是事件。但这远远超出了这个问题的范围。所以我们会保持自己的 Action 状态。

您遇到的问题是您正在 UI 线程中执行您的操作。您需要生成一个工作线程并忽略后续事件,直到您的操作完成。

在我给出的示例中,当按下或按住字母“a”时,我开始了一个新 Action 。在第一个 Action 完成之前,它不会产生另一个 Action 。该操作更新表单上的标签,显示在完成之前还剩下多少“周期”。

还有另一个标签显示到目前为止发生了多少 Action 。

生成新 Action

重要的部分是让所有 UI 键事件发生,而不是在 UI 线程中阻塞导致它们排队。

public void keyPressed(KeyEvent e) {
char keyChar = e.getKeyChar();
System.out.println("KeyChar: " + keyChar);
// Press a to start an Action
if (keyChar == 'a') {
if (!mAction.isRunning()) {
mTotalActions.setText("Ran " + (++mTotalActionsRan) + " actions.");
System.out.println("Starting new Action");
Thread thread = new Thread(new Runnable() {
public void run() {
mAction.run();
}
});
thread.start();
}
}
}

UI 线程更新

如果您的操作对用户界面执行任何类型的更新,则需要使用 SwingUtilities.invokeLater方法。此方法将使您的代码排队以在 UI 线程中运行。您不能在 UI 线程以外的线程中修改用户界面。此外,仅使用 SwingUtilities 来更新 UI 组件。任何不调用组件方法的计算、处理等都可以在 SwingUtilities.invokeLater 的范围之外完成。

完整代码 list
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package stackoverflow_4589538;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class Main extends JFrame {

private JLabel mActionLabel;
private JLabel mTotalActions;
private int mTotalActionsRan;

private class MyAction {

private boolean mIsRunning = false;

public void run() {
// Make up a random wait cycle time
final int cycles = new Random().nextInt(100);
for (int i = 0; i < cycles; ++i) {
final int currentCycle = i;
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
mActionLabel.setText("Cycle " + currentCycle + " of " + cycles);
}
});
}
completed();
}

public synchronized void start() {
mIsRunning = true;
}

public synchronized void completed() {
mIsRunning = false;
}

public synchronized boolean isRunning() {
return mIsRunning;
}
}
private MyAction mAction = new MyAction();

public Main() {
setLayout(null);
setBounds(40, 40, 800, 600);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
addKeyListener(new KeyAdapter() {

@Override
public void keyPressed(KeyEvent e) {
char keyChar = e.getKeyChar();
System.out.println("KeyChar: " + keyChar);
// Press A to start an Action
if (keyChar == 'a') {
if (!mAction.isRunning()) {
mTotalActions.setText("Ran " + (++mTotalActionsRan) + " actions.");
System.out.println("Starting new Action");
Thread thread = new Thread(new Runnable() {

public void run() {
mAction.run();
}
});
// I had this within the run() method before
// but realized that it is possible for another UI event
// to occur and spawn another Action before, start() had
// occured within the thread
mAction.start();
thread.start();
}
}
}

@Override
public void keyReleased(KeyEvent e) {
}
});

mActionLabel = new JLabel();
mActionLabel.setBounds(10, 10, 150, 40);

mTotalActions = new JLabel();
mTotalActions.setBounds(10, 50, 150, 40);

add(mActionLabel);
add(mTotalActions);
}

public static void main(String[] args) {
new Main().setVisible(true);
}
}

关于java - 跳过 Java KeyEvents,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4589538/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com