I have created a small app that uses JButtons to increment numbers. 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). 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. 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). I've tried so many things my head is spinning, trying to add either to my main method with frame or my controller class. 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.
The following uses JComponent.WHEN_IN_FOCUSED_WINDOW
to define the context under which the key events will be generated. 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
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. 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.