首页 > 解决方案 > 除非先单击 JButton,否则 keyPressed 不起作用

问题描述

我创建了一个使用 JButtons 递增数字的小应用程序。这些按钮不应该是可点击的,而是由键盘激活(即文本字段中的数字随着键盘的按下而不是通过使用鼠标单击按钮而增加)。我的问题是,当应用程序首次启动时,在我第一次单击其中一个按钮之前,键盘不会做任何事情——即使单击按钮没有任何进展。我试图让其中一个按钮requestFocusInWindow()认为如果它已经被关注,那么这些键就会起作用,但无论我把它放在我的主要方法还是控制器类中,这似乎都不起作用。我试图弄清楚我是否需​​要做 aKeyboardFocusManager或 aaddFocusListener()(但我不希望按钮获得/失去焦点时总是发生某些事情)。我已经尝试了很多让我头晕目眩的事情,试图通过框架或控制器类添加到我的主要方法中。以下是我当前的代码:

主类

import javax.swing.JFrame;

public class Count {

    public static void main(String[] args) {
        CountController frame = new CountController();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(560, 150); 
        frame.setVisible(true); 
        //I've tried to add the button and requestFocusInWindow here
        //as well as tried a frame.addWindowFocusListener
    }
} // end class

控制器类

imports ...
public class CountController extends JFrame implements KeyListener {
    private JLabel ...
    private JTextField ...
    private JButton ....
    int ...
    // no-argument constructor
    public CountController() {
        super("Title");
        setLayout(null); // position GUI components explicitly

        //set up JLabels in following manner
        label = new JLabel("some label");
        label.setBounds(47, 5, 45, 25);
        label.setHorizontalAlignment(JLabel.CENTER);
        add(label);

        //set up JTextFields in following manner
        textField = new JTextField("0");
        textField.setBounds(47, 30, 45, 25);
        textField.setHorizontalAlignment(JTextField.CENTER);
        textField.setBackground(Color.WHITE);
        textField.setEditable(false);
        add(textField);

        //set up JButtons in the following manner
        button = new JButton("some text");
        button.setBounds(15, 70, 110, 25);
        button.setBackground(Color.WHITE);
        add(button);
        button.addKeyListener(this);
        //I've tried adding requestFocusInWindow() here as well
    } // end constructor

    //begin KeyListener stuff
    @Override
    public void keyPressed(KeyEvent event){
        int keyCode = event.getKeyCode();
        switch(keyCode){
            case #: //# is ASCII #
                do some things;
                call a method();
                break;
        }
    }
    @Override
    public void keyReleased(KeyEvent event){
        button.setBackground(Color.WHITE);
    }
    @Override
    public void keyTyped(KeyEvent event){
        // nothing but this is needed for implementing KeyListener
    }

    //List of methods that are called from switch
        ...

    //I've tried to add a public void initialize(){}

}//end CountController class

我将不胜感激任何关于让它工作的意见,这样我就不必在我的按键工作之前先点击一个按钮。谢谢!

标签: javafocusjbuttonkeylistener

解决方案


为了让监听器触发事件​​,它注册到的组件必须首先获得焦点并获得焦点。请改用键绑定 API

以下用于JComponent.WHEN_IN_FOCUSED_WINDOW定义生成关键事件的上下文。在此配置中,无论什么具有焦点,事件仍然会生成,只要窗口当前处于焦点状态

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;

public class Count {

  public static void main(String[] args) {
    CountController frame = new CountController();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(560, 150);
    frame.setVisible(true);
    //I've tried to add the button and requestFocusInWindow here
    //as well as tried a frame.addWindowFocusListener
  }

  public static class CountController extends JFrame {

    // no-argument constructor
    public CountController() {
      super("Title");
      setLayout(new GridBagLayout());
      GridBagConstraints gbc = new GridBagConstraints();
      gbc.gridwidth = GridBagConstraints.REMAINDER;

      //set up JLabels in following manner
      JLabel label = new JLabel("some label");
      label.setHorizontalAlignment(JLabel.CENTER);
      add(label, gbc);

      //set up JTextFields in following manner
      JTextField textField = new JTextField("0", 20);
      textField.setHorizontalAlignment(JTextField.CENTER);
      textField.setBackground(Color.WHITE);
      textField.setEditable(false);
      add(textField, gbc);

      //set up JButtons in the following manner
      JButton button = new JButton("some text");
      add(button, gbc);

      InputMap im = button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
      ActionMap am = button.getActionMap();

      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_3, KeyEvent.SHIFT_DOWN_MASK), "Pressed.#");
      am.put("Pressed.#", new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
          textField.setText(textField.getText() + "#");
        }
      });

    } // end constructor

  }//end CountController class
} // end class

虽然我会针对父容器而不是按钮注册绑定,但这只是我。

而且,不使用null布局的原因......这就是你的原始代码在我的电脑上的样子

不使用空布局的原因


推荐阅读