From what I understand, essentially you want to have the same operation of a button assigned to a specific key stroke.
Things you want to avoid are KeyListener
, especially because you have other focusable components in the view, namely buttons, which will steal keyboard focus and render the KeyListener
useless. This is why, in almost all cases, you want to avoid KeyListener
.
A better and more reliable solution would be to use the Key Bindings API, which overcomes this focus related issue, but it also encourages the use of reusable components of work through the Action
s API
Something like...
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.StringJoiner;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
JTextField field = new JTextField(10);
field.setEditable(false);
field.setFocusable(false);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_1, 0), "Pressed.One");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_2, 0), "Pressed.Two");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_3, 0), "Pressed.Three");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_4, 0), "Pressed.Four");
am.put("Pressed.One", new OrderAction(1, field));
am.put("Pressed.Two", new OrderAction(2, field));
am.put("Pressed.Three", new OrderAction(3, field));
am.put("Pressed.Four", new OrderAction(4, field));
JButton btnOne = new JButton(new OrderAction(1, field));
JButton btnTwo = new JButton(new OrderAction(2, field));
JButton btnThree = new JButton(new OrderAction(3, field));
JButton btnFour = new JButton(new OrderAction(4, field));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 0;
gbc.gridy = 1;
add(btnOne, gbc);
gbc.gridx++;
add(btnTwo, gbc);
gbc.gridx = 0;
gbc.gridy++;
add(btnThree, gbc);
gbc.gridx++;
add(btnFour, gbc);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 2;
add(field, gbc);
}
protected class OrderAction extends AbstractAction {
private int value;
private JTextField field;
public OrderAction(int value, JTextField field) {
this.value = value;
this.field = field;
switch (value) {
case 1:
putValue(NAME, "Coffe");
break;
case 2:
putValue(NAME, "Latte");
break;
case 3:
putValue(NAME, "Espresso");
break;
case 4:
putValue(NAME, "Vanilla Latte");
break;
}
}
@Override
public void actionPerformed(ActionEvent e) {
StringJoiner sj = new StringJoiner("; ");
if (field.getText() != null && field.getText().length() > 0) {
sj.add(field.getText());
}
sj.add(Integer.toString(value));
field.setText(sj.toString());
}
}
}
}
Note, you could apply the key bindings directly to each button instead
Now, if you want to "visually" press the button on a key stroke, I would recommend either creating a custom JButton
or factory method, which could allow for a more simplified implementation, but the basic idea would be to define a key binding and Action
which simply called the buttons doClick
method, for example
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.StringJoiner;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
JTextField field = new JTextField(10);
field.setEditable(false);
field.setFocusable(false);
JButton btnOne = new JButton(new OrderAction(1, field));
JButton btnTwo = new JButton(new OrderAction(2, field));
JButton btnThree = new JButton(new OrderAction(3, field));
JButton btnFour = new JButton(new OrderAction(4, field));
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_1, 0), "Pressed.One");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_2, 0), "Pressed.Two");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_3, 0), "Pressed.Three");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_4, 0), "Pressed.Four");
am.put("Pressed.One", new ProxyAction(btnOne));
am.put("Pressed.Two", new ProxyAction(btnTwo));
am.put("Pressed.Three", new ProxyAction(btnThree));
am.put("Pressed.Four", new ProxyAction(btnFour));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 0;
gbc.gridy = 1;
add(btnOne, gbc);
gbc.gridx++;
add(btnTwo, gbc);
gbc.gridx = 0;
gbc.gridy++;
add(btnThree, gbc);
gbc.gridx++;
add(btnFour, gbc);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 2;
add(field, gbc);
}
protected class ProxyAction extends AbstractAction {
private JButton btn;
public ProxyAction(JButton btn) {
this.btn = btn;
}
@Override
public void actionPerformed(ActionEvent e) {
btn.doClick();
}
}
protected class OrderAction extends AbstractAction {
private int value;
private JTextField field;
public OrderAction(int value, JTextField field) {
this.value = value;
this.field = field;
switch (value) {
case 1:
putValue(NAME, "Coffe");
break;
case 2:
putValue(NAME, "Latte");
break;
case 3:
putValue(NAME, "Espresso");
break;
case 4:
putValue(NAME, "Vanilla Latte");
break;
}
}
@Override
public void actionPerformed(ActionEvent e) {
StringJoiner sj = new StringJoiner("; ");
if (field.getText() != null && field.getText().length() > 0) {
sj.add(field.getText());
}
sj.add(Integer.toString(value));
field.setText(sj.toString());
}
}
}
}