简体   繁体   English

除非先单击JButton,否则keyPressed不起作用

[英]keyPressed doesn't work unless JButton clicked first

I have created a small app that uses JButtons to increment numbers. 我创建了一个使用JButton递增数字的小应用程序。 The buttons aren't supposed to be clickable but rather be activated by keyboard (ie the numbers in the textField increase with the keyboard pushed and not by using a mouse to click the button). 这些按钮不是可单击的,而是由键盘激活的(即textField中的数字随键盘的按下而增加,而不是通过鼠标单击按钮来增加)。 My issue is that when the app is first launched, the keyboard doesn't do anything until I first click one of the buttons - even though clicking the button doesn't progress anything. 我的问题是,在首次启动该应用程序时,键盘没有执行任何操作,直到我先单击其中一个按钮为止-即使单击该按钮不会执行任何操作。 I have tried to make one of the buttons requestFocusInWindow() thinking that if it was already focused on, the the keys would work, but that hasn't seemed to work whether I put it in my main method or controller class. 我试图使按钮之一requestFocusInWindow()认为,如果它已经集中在上面,那么键就可以工作,但是无论将其放在主方法还是控制器类中,这似乎都行不通。 I've tried to figure out if I need to do a KeyboardFocusManager or a addFocusListener() (but I don't want something always happening if a button gains/loses focus). 我试图找出是否需要执行KeyboardFocusManageraddFocusListener() (但是我不希望按钮获得/失去焦点时总会发生某些事情)。 I've tried so many things my head is spinning, trying to add either to my main method with frame or my controller class. 我已经尝试了很多东西,试图将其添加到带有frame的主方法或控制器类中。 Below is what my current code is: 以下是我当前的代码:

Class with Main 主班

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

Controller 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

I would appreciate any input on getting this to work so that I don't have to first click a button before my keys work. 我将不胜感激,希望它能起作用,因此我不必先单击按钮即可操作键。 Thanks! 谢谢!

In order for the listener to trigger an event, the component it is registered to must first BE focused AND have focus. 为了使侦听器触发事件​​,必须先将其注册为组件并使其具有焦点。 Use the key bindings API instead. 请改用按键绑定API

The following uses JComponent.WHEN_IN_FOCUSED_WINDOW to define the context under which the key events will be generated. 下面使用JComponent.WHEN_IN_FOCUSED_WINDOW定义将在其下生成键事件的上下文。 In this configuration, it won't matter what has focus, the events will still be generated, so long as the window is currently focused 在这种配置下,什么焦点都没有关系,只要窗口当前处于焦点状态,事件仍然会生成

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

Although I'd register the bindings against the parent container and not the buttons, but that's just me. 尽管我将绑定绑定注册到父容器而不是按钮上,但这仅是我自己。

And, reasons for not using null layouts ... this is what your original code looks like on my PC 而且,不使用null布局的原因...这就是您原始代码在我的PC上的样子

不使用空布局的原因

Although it's not quite clear to me what your code should accomplish, your problem is that you addKeyListener(this) to the button but your button doesn't have the focus and the key doesn't do anything when pressed. 尽管我不清楚您的代码应该完成什么操作,但是您的问题是您将addKeyListener(this)到了button但是按钮没有焦点,并且按下键时它什么也没做。 Try adding the KeyListener() to some other GUI component, like the textfield for example, since it's the first component and has the focus on start(from the code you've provided), and see if it works. 尝试将KeyListener()添加到其他GUI组件(例如, textfield ,因为它是第一个组件,并且专注于start(从您提供的代码开始),然后查看它是否起作用。

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

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