【问题标题】:Clicking a JButton from keyboard using KeyListener使用 KeyListener 从键盘单击 JButton
【发布时间】:2020-07-13 05:55:40
【问题描述】:

就像我在标题中描述的那样,如果按下键盘上的一个键,我需要点击一个 JButton。例如:

ActionListenerClass actionListener = new ActionListenerClass();
KeyListenerClass actionListener = new KeyListenerClass();
JButton aButton = new JButton("A");
aButton.setActionCommand("A");
aButton.addActionListener(actionListener);
aButton.addKeyListener(keyListener);

当从键盘按下“A”时,按钮 A 将执行 doClick() 并将操作命令发送到操作侦听器的私有类以进行事件处理。现在看了很多stackoverflow的解决方法,都是用key binding,就是在input map和action map之间进行绑定。问题是我绝对必须使用带有私有类而不是绑定的键侦听器。我现在唯一能猜到的是上面的 keyListener 必须以某种方式接收键盘输入并在 keyPressed 方法中绑定到它的按钮上执行 doClick,我已经尝试过,但它根本不起作用。

编辑:这是我的完整代码。

  1. CalculatorViewController.java



import java.awt.*;
import java.awt.event.*;
import java.util.regex.Pattern;

import javax.swing.*;
/**Create the app GUI
 * @author Bach Le
 * @version 1.0
 * @see java.awt, java.awt.event, javax.swing
 * @since 12.0.1
 */
public class CalculatorViewController extends JPanel   {

    
    private JButton backSpaceButton;
     public CalculatorViewController() {
    Controller controller = new Controller();
    KeyController keyController  = new KeyController();

    
    
    setBorder(BorderFactory.createMatteBorder(5, 5, 5, 5,Color.black));//Adding the panel border
    
    
     backSpaceButton = new JButton("\u21DA");

    backSpaceButton.setPreferredSize(new Dimension(52,55));
    backSpaceButton.setOpaque(false);//set transparency
    backSpaceButton.setContentAreaFilled(false);
    backSpaceButton.setBorderPainted(false);
    backSpaceButton.setActionCommand("Backspace Button");//set the action command
    backSpaceButton.addActionListener(controller);//add action listener
    backSpaceButton.setToolTipText("Backspace (Alt+B)");//set tooltip text
    backSpaceButton.setFont(font);//set the font
    backSpaceButton.addKeyListener(keyController);
   
   add(backSpaceButton) ;
   
 
   



}
    


private class Controller implements ActionListener{
public void actionPerformed(ActionEvent e) {
//event handling here
}
}

private class KeyController implements KeyListener{

    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub
    
    }

    @Override
    public void keyPressed(KeyEvent e) {
    if(e.getKeyCode()==65) {
        backSpaceButton.doClick();
        
    }
        
    }

    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub
        
    }
    
    
    
    
    
}

}

2.Calculator.java

public class Calculator {
    public static void main(String[] args) {
          CalculatorViewController pane = new CalculatorViewController();
            
             JFrame frame = new JFrame("Calculator");
           frame.setContentPane(pane);  
            frame.setSize(380, 520);
            frame.setLocationByPlatform(true);
            frame.setResizable(true);
            frame.setVisible(true);
       }

}

关注CalculatorViewController,我试图在按下A时点击backSpaceButton(当然它是实际的退格按钮,但我稍后会修复它),所以它会将其动作命令发送到注册到它的动作监听器,将在Controller内部类的方法中处理。我不确定实现这一目标的正确方法。

【问题讨论】:

  • 没用是什么意思? keyPressed 事件没有被触发吗?你能向我们展示你所有的代码吗?
  • @PiRocks 他们现在被添加
  • 你真的需要这么多代码来说明问题吗?你有几个按钮,你想用一个关键的监听器来触发这些按钮?最好的解决方案是在 jframe 上使用输入图/动作图。这样你就不需要专注了,因为你有多个按钮。默认情况下,空间应该触发一个焦点按钮吗?
  • @matt 我把我所有的代码都粘贴在那里,这样人们就可以按照他们的意愿重复我的问题。如果您不需要它,那么第一个代码块就足够了。不,我不允许使用哈希映射进行绑定(这是一个分配规范)
  • “不,我不允许使用哈希映射进行绑定” 我没有说任何关于哈希映射的事情。第一个代码块是不够的,您应该创建一个最小的可重现示例。 stackoverflow.com/help/mcve

标签: java swing


【解决方案1】:

添加 KeyListener 仅适用于具有焦点的组件。您不希望将 KeyListener 添加到 JButton,因为只有一个 JButton 会成为焦点。

如果只是设置一个值,您可以使用setMnemonic,但是当您按下该键时,您必须使用修饰符(例如 'alt)。

“正确”的做法是使用key bindings

这是一个带有两个按钮的示例。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ButtonKeys{
    
    public void buildGui(){
        JFrame frame = new JFrame("key buttons");
        JPanel panel = new JPanel(new BorderLayout());
        JButton a = new JButton("A");
        a.addActionListener(evt->{ System.out.println("a pressed");});
        JButton b = new JButton("B");
        b.addActionListener(evt->{ System.out.println("b pressed");});
        
        panel.add(a, BorderLayout.EAST);
        panel.add(b, BorderLayout.WEST);
        
        frame.setContentPane(panel);
        frame.setVisible(true);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        KeyStroke us = KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false);
        panel.getInputMap().put(us, "A");
        panel.getActionMap().put("A", new AbstractAction(){
            @Override
            public void actionPerformed(ActionEvent evt){
               a.doClick();
            }
        });
        
        KeyStroke us2 = KeyStroke.getKeyStroke(KeyEvent.VK_B, 0, false);
        panel.getInputMap().put(us2, "B");
        panel.getActionMap().put("B", new AbstractAction(){
            @Override
            public void actionPerformed(ActionEvent evt){
               b.doClick();
            }
        });
        a.setFocusable(false);
        b.setFocusable(false);

    }

    public static void main(String[] args){
        EventQueue.invokeLater( new ButtonKeys()::buildGui);
    }
}

我将按钮设置为不获得焦点,因为如果它们获得焦点,则将使用其输入映射。

【讨论】:

    【解决方案2】:

    此代码应该适合您。对于 KeyListener,我使用了 KeyAdapter more here,因为如果您只需要使用其中一种方法,它会更方便。如果需要,您当然可以将侦听器移动到单独的类中,但行为将保持不变。

    public static void main(String[] args) {
    
        JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        
        JButton btn = new JButton("A");
        btn.addActionListener(new ActionListener() {
            
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Button clicked");
            }
        });
        btn.addKeyListener(new KeyAdapter() {
            public void keyTyped(KeyEvent e) {
                if (e.getKeyChar() == 'A' || e.getKeyChar() == 'a') {
                    ((JButton) e.getSource()).doClick();
                }
            }
        });
        panel.add(btn);
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(0, 0, 800, 600);
        frame.getContentPane().add(panel);
        frame.setVisible(true);
    }
    

    如果你真的需要使用KeyListener,它看起来像这样:

        btn.addKeyListener(new KeyListener() {
            
            @Override
            public void keyTyped(KeyEvent e) {
                if (e.getKeyChar() == 'A' || e.getKeyChar() == 'a') {
                    ((JButton) e.getSource()).doClick();
                }
            }
            
            @Override
            public void keyReleased(KeyEvent e) {
                // TODO Auto-generated method stub
                
            }
            
            @Override
            public void keyPressed(KeyEvent e) {
                // TODO Auto-generated method stub
                
            }
        });
    

    【讨论】:

    • 我在我的 backSpaceButton 上试过了。没用,是不是和按钮没有聚焦有关?
    • 是的,没错。当然,您的按钮只有在具有焦点时才会接收 KeyEvents。否则,您将不得不使用 KeyBindings,但您说无论出于何种原因您都不想要它。您可以告诉您的按钮请求焦点或将KeyListener 添加到将具有焦点的组件(例如面板)。
    猜你喜欢
    • 1970-01-01
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    • 2013-10-04
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    • 1970-01-01
    相关资源
    最近更新 更多