JButton KeyPressed - 没有任何反应
JButton KeyPressed - Nothing Happens
我正在努力使按右箭头键的效果与按 JButton
的效果相同。我可以将右箭头键绑定到按钮本身——但这意味着我必须在右键起作用之前按下按钮。现在我想看看是否绑定到实际的 JFrame
是我想要的,但是当我绑定到框架时我根本无法发生任何事情:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
onButtonPress();
}
private void formKeyPressed(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_RIGHT){
onButtonPress();
}
}
private void onButtonPress() {
pressNum++;
jLabel1.setText("Button has been pressed " + pressNum + " times.");
}
根据一般经验,您应该避免 KeyListener
。主要原因是,为了让 KeyListener
生成按键事件,它注册到的组件必须是可聚焦的并且具有键盘焦点。在您的情况下,这可能意味着向 UI 中的每个组件添加一个 KeyListener
,从而 "might" 获得键盘焦点,这在现实世界中并不实用。
相反,您应该使用 Key Bindings API,它为您提供了定义触发相关操作所需的焦点级别的方法。
键绑定 API 和示例使用了 Action
s API,它允许我定义一个可应用于多个 "actionable" 控件的工作单元
该示例还使用了 delegate/callback/listener(即 CounterListener
),它允许我将 "side effects" 与操作本身分离。
这基本上意味着 Action
可以做它需要做的事情,但是 "other" 感兴趣的人可以在它发生变化时执行一些其他的操作。同样,您可以将 ActionListener
附加到 Action
,但这只是实施起来更简单、更快捷
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.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.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() {
JLabel label = new JLabel("...");
MyAwesomeAction action = new MyAwesomeAction(new CounterListener() {
@Override
public void counterChanged(int count) {
label.setText("Button has been pressed " + count + " times");
}
});
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
JButton button = new JButton(action);
add(button, gbc);
add(label, gbc);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "MakeItSo");
am.put("MakeItSo", action);
}
}
public interface CounterListener {
public void counterChanged(int count);
}
public class MyAwesomeAction extends AbstractAction {
private int count;
private CounterListener listener;
public MyAwesomeAction(CounterListener listener) {
putValue(NAME, "Make it so");
this.listener = listener;
}
@Override
public void actionPerformed(ActionEvent e) {
count++;
listener.counterChanged(count);
}
}
}
这个例子有一个 JButton
和两个侦听器:一个 ActionListener
和一个 KeyListener
。关键侦听器是通过 KeyAdapter
抽象 class 实现的。来自 API 文档:
KeyAdapter
is for receiving keyboard events. The methods in this class
are empty. This class exists as convenience for creating listener
objects.
Create a listener object using the extended class and then register it
with a component using the component's addKeyListener
method. When a
key is pressed, released, or typed, the relevant method in the
listener object is invoked, and the KeyEvent
is passed to it.
示例代码:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ButtonListeners {
private JLabel label;
private int counter;
public static void main(String [] args) {
new ButtonListeners().gui();
}
private void gui() {
JFrame frame = new JFrame();
frame.setTitle("JButton Listeners");
JButton button = new JButton("jButton1");
button.addActionListener(actionEvent -> displayLabel());
button.addKeyListener(new ButtonKeyPressListener());
label = new JLabel("Press button or -> key");
frame.add(button, BorderLayout.SOUTH);
frame.add(label, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(300, 150);
frame.setVisible(true);
}
private void displayLabel() {
label.setText("Action count: " + ++counter);
}
private class ButtonKeyPressListener extends KeyAdapter {
@Override public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT){
displayLabel();
}
}
}
}
我正在努力使按右箭头键的效果与按 JButton
的效果相同。我可以将右箭头键绑定到按钮本身——但这意味着我必须在右键起作用之前按下按钮。现在我想看看是否绑定到实际的 JFrame
是我想要的,但是当我绑定到框架时我根本无法发生任何事情:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
onButtonPress();
}
private void formKeyPressed(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_RIGHT){
onButtonPress();
}
}
private void onButtonPress() {
pressNum++;
jLabel1.setText("Button has been pressed " + pressNum + " times.");
}
根据一般经验,您应该避免 KeyListener
。主要原因是,为了让 KeyListener
生成按键事件,它注册到的组件必须是可聚焦的并且具有键盘焦点。在您的情况下,这可能意味着向 UI 中的每个组件添加一个 KeyListener
,从而 "might" 获得键盘焦点,这在现实世界中并不实用。
相反,您应该使用 Key Bindings API,它为您提供了定义触发相关操作所需的焦点级别的方法。
键绑定 API 和示例使用了 Action
s API,它允许我定义一个可应用于多个 "actionable" 控件的工作单元
该示例还使用了 delegate/callback/listener(即 CounterListener
),它允许我将 "side effects" 与操作本身分离。
这基本上意味着 Action
可以做它需要做的事情,但是 "other" 感兴趣的人可以在它发生变化时执行一些其他的操作。同样,您可以将 ActionListener
附加到 Action
,但这只是实施起来更简单、更快捷
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.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.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() {
JLabel label = new JLabel("...");
MyAwesomeAction action = new MyAwesomeAction(new CounterListener() {
@Override
public void counterChanged(int count) {
label.setText("Button has been pressed " + count + " times");
}
});
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
JButton button = new JButton(action);
add(button, gbc);
add(label, gbc);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "MakeItSo");
am.put("MakeItSo", action);
}
}
public interface CounterListener {
public void counterChanged(int count);
}
public class MyAwesomeAction extends AbstractAction {
private int count;
private CounterListener listener;
public MyAwesomeAction(CounterListener listener) {
putValue(NAME, "Make it so");
this.listener = listener;
}
@Override
public void actionPerformed(ActionEvent e) {
count++;
listener.counterChanged(count);
}
}
}
这个例子有一个 JButton
和两个侦听器:一个 ActionListener
和一个 KeyListener
。关键侦听器是通过 KeyAdapter
抽象 class 实现的。来自 API 文档:
KeyAdapter
is for receiving keyboard events. The methods in this class are empty. This class exists as convenience for creating listener objects.Create a listener object using the extended class and then register it with a component using the component's
addKeyListener
method. When a key is pressed, released, or typed, the relevant method in the listener object is invoked, and theKeyEvent
is passed to it.
示例代码:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ButtonListeners {
private JLabel label;
private int counter;
public static void main(String [] args) {
new ButtonListeners().gui();
}
private void gui() {
JFrame frame = new JFrame();
frame.setTitle("JButton Listeners");
JButton button = new JButton("jButton1");
button.addActionListener(actionEvent -> displayLabel());
button.addKeyListener(new ButtonKeyPressListener());
label = new JLabel("Press button or -> key");
frame.add(button, BorderLayout.SOUTH);
frame.add(label, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(300, 150);
frame.setVisible(true);
}
private void displayLabel() {
label.setText("Action count: " + ++counter);
}
private class ButtonKeyPressListener extends KeyAdapter {
@Override public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT){
displayLabel();
}
}
}
}