Java Swing : Do something while the key is being pressed

标签 java swing keyboard key-bindings onkeypress

我正在使用 KeyAdpater 获取事件和方法 addKeyListener 并且工作正常。问题是,当按下键时, Action 只发生一次,而不是在按下时发生,按住键 3-4 秒后, Action 一直发生,这正是我想要的。

我想知道是否有好的方法可以一直从一开始按下按键,而不是在按住 3-4 秒之后一直执行该操作。

我想到了下一个解决方案,但也许已经有一个实现的方法:

public abstract class MyKeyAdapter extends KeyAdapter{
    private boolean isPressed = false;
    private int pressedKey = 0;
    Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            while(isPressed)
                keyPressedAction(pressedKey);
        }
    });    

    @Override
    public void keyPressed(KeyEvent e) {
            if(!isPressed){
                pressedKey = e.getKeyCode();
                t.start();
            }
    }
    @Override
    public void keyReleased(KeyEvent e) {
         if(isPressed && e.getKeyCode()==pressedKey)}
             isPressed = false;
    }

    public abstract void keyPressedAction(int key);
}

最佳答案

我通过使用 Key Bindings 取得了很好的成功,而不是 KeyListener,并启动 Swing Timer在按键上,然后停止 Timer on Swing 释放。您可以通过将正确的 KeyStroke 对象传递到绑定(bind)组件的 InputMap 来区分按键按下和释放。使用此处找到的 KeyStroke.getKeyStroke(int keyCode, int modifiers, boolean onKeyRelease) 方法:KeyStroke API .如果 boolean 参数为假,输入将响应按键,如果参数为真则相反。

举个简单粗暴的例子:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.*;

@SuppressWarnings("serial")
public class KeyBindingEg extends JPanel {
   private static final String UP_KEY_PRESSED = "up key pressed";
   private static final String UP_KEY_RELEASED = "up key released";
   private static final int UP_TIMER_DELAY = 200;
   private static final Color FLASH_COLOR = Color.red;

   private Timer upTimer;
   private JLabel label = new JLabel();

   public KeyBindingEg() {
      label.setFont(label.getFont().deriveFont(Font.BOLD, 32));
      label.setOpaque(true);
      add(label);

      setPreferredSize(new Dimension(400, 300));

      int condition = WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition);
      ActionMap actionMap = getActionMap();
      KeyStroke upKeyPressed = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false);
      KeyStroke upKeyReleased = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true);

      inputMap.put(upKeyPressed, UP_KEY_PRESSED);
      inputMap.put(upKeyReleased, UP_KEY_RELEASED);

      actionMap.put(UP_KEY_PRESSED, new UpAction(false));
      actionMap.put(UP_KEY_RELEASED, new UpAction(true));

   }

   private class UpAction extends AbstractAction {
      private boolean onKeyRelease;

      public UpAction(boolean onKeyRelease) {
         this.onKeyRelease = onKeyRelease;
      }

      @Override
      public void actionPerformed(ActionEvent evt) {
         if (!onKeyRelease) {
            if (upTimer != null && upTimer.isRunning()) {
               return;
            }
            System.out.println("key pressed");
            label.setText(UP_KEY_PRESSED);

            upTimer = new Timer(UP_TIMER_DELAY, new ActionListener() {

               @Override
               public void actionPerformed(ActionEvent e) {
                  Color c = label.getBackground();
                  if (FLASH_COLOR.equals(c)) {
                     label.setBackground(null);
                     label.setForeground(Color.black);
                  } else {
                     label.setBackground(FLASH_COLOR);
                     label.setForeground(Color.white);
                  }
               }
            });
            upTimer.start();
         } else {
            System.out.println("Key released");
            if (upTimer != null && upTimer.isRunning()) {
               upTimer.stop();
               upTimer = null;
            }
            label.setText("");
         }
      }

   }

   private static void createAndShowGui() {
      KeyBindingEg mainPanel = new KeyBindingEg();

      JFrame frame = new JFrame("KeyBindingEg");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

关于Java Swing : Do something while the key is being pressed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10544956/

相关文章:

android - 如何在屏幕底部创建一个不是矩形的屏幕安卓键盘?

python - 有效的键盘输入处理

java - EJB 3 stub 生成

java - Rest API 调用可在极短的时间内从多个 API 提供商获取数据 : Example websites like makemytrip

java - 为什么我的paintComponent 不工作?

java - JTable 在 INSERT 后隐藏表头

Java Swing 用鼠标移动形状

java - 如何使用 Scanner.nextLine()

java - 使用反射的静态方法

java - LWJGL 按键事件状态不起作用