【问题标题】:Add KeyListener to Jframe issue将 KeyListener 添加到 Jframe 问题
【发布时间】:2017-02-13 18:40:42
【问题描述】:

我有一个我在 Netbeans 中制作的 jframe,这个 jframe 正在由另一个 java 类“启动”,但对于当前的问题并不重要。重要的是我似乎无法弄清楚如何将我的关键监听器添加到我的这个 jframe 中。我已经实现了按键监听器,添加了所需的功能(按键输入、按键按下和按键释放)。但我不知道如何实际添加/启动实际的键监听器,以使其工作。

到目前为止,我已经尝试了两种不同的方法,首先我尝试在代码的开头添加行 addKeylistener(new JFrameList());,其中实际的 jframe 正在启动,但这样做实际的框架甚至不会显示。除此之外,我还尝试在另一个函数callJframFForm() 中添加同一行,该函数在调用 jframe 的同时从另一个类调用。但这只会返回错误non-static method addKeyListener(KeyListener) cannot be referenced from a static context。我不确定还有什么其他方法可以添加关键侦听器,因此正在寻求一些帮助。

目前我的代码如下所示。

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class JFrameList extends javax.swing.JFrame implements KeyListener{

    public static String keyPresCod = "";

    public JFrameList() {
        initComponents();
        addKeyListener(new JFrameList()); //This is where I am currently trying to call from, but frame won't show
    }    

    public static void main(String args[]) {
        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new JFrameList().setVisible(true);
            }
        });  
    }                                                

    // Variables declaration - do not modify                    
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    // End of variables declaration                  

    static void callJframFForm(){
        try {
            //This is where I have also tried to add the initialization line
        } catch(Exception e) {
            e.printStackTrace();
    }
    }

    @Override
    public void keyTyped(KeyEvent e) {
        int codeFKey = e.getKeyCode();

        if (codeFKey == KeyEvent.VK_A) {
            System.out.println("Button A clicked");
                        keyPresCod = "A";
        } else if (codeFKey == KeyEvent.VK_B) {
            System.out.println("Button B clicked");
                        keyPresCod = "B";
        } else {
            System.out.println("Different key pressed");
                        keyPresCod = "Another key";
        }
    }

    @Override
    public void keyPressed(KeyEvent e) {

    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

}

【问题讨论】:

  • 我认为您当前的方法过于矫枉过正,我会看看How to Use Buttons, Check Boxes, and Radio Buttons,因为按钮具有用户习惯使用的预定义工作方式
  • @MadProgrammer - I'd have a look at... - 很高兴你同意。
  • @camickr 但鉴于 OP 试图解决的问题缺乏上下文,我不知道这是否是答案 ;)
  • 非常感谢您的输入,我的代码的全部目的是能够显示已单击计算机键盘上的哪个按钮而不是 JButton。到目前为止,我有很多关于如何更改代码的灵感,所以我必须先检查一下。

标签: java swing netbeans keylistener keyevent


【解决方案1】:

问题

addKeyListener(new JFrameList())

这会创建一个新的JFrameList 对象并使用它的监听器。这意味着任何击键都存储在新对象的成员中。要查看结果,您必须这样做

JFrameList 列表 = 新的 JFrameList(); addKeyListener(list); //使用列表变量访问keyPressed代码

这当然不是你想要的行为。您希望将击键存储在当前实例中,而不是新对象中。这意味着你应该这样做

addKeyListener(this)

尽管您可能会注意到侦听器仅“有时”工作,或者可能根本不工作,具体取决于您的测试方式。

Swing 使用焦点系统来管理哪些侦听器应该接收事件,并且由于您将侦听器添加到 JFrame,因此侦听器将仅在框架处于焦点时接收事件。

解决方案

你应该use key bindings rather than a key listener。

如果你选择继续使用监听器,你应该把它添加到你的按钮,而不是你的框架:

jButton1.addKeyListener(this);
jButton2.addKeyListener(this);

您可以通过调用event.getSource() 来获取事件源(您的按钮),而不是检查事件的关键代码。

键绑定允许您为组件设置灵活的焦点设置。您需要做的就是访问组件的输入映射:

String actionCommand = "Press Button A";
jButton1.setActionCommand(actionCommand);
jButton1.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("A"), actionCommand);
jButton1.getActionMap(actionCommand, this);

您的JFrameList 现在应该实现ActionListener 而不是KeyListener,因为它将接收您的事件作为操作:

class JFrameList extends JFrame implements ActionListener {
    private JButton jButton1;

    public JFrameList() {
        jButton1 = new JButton("A");
        //set action command, add to input map, add to action map
    }

    public void actionPerformed(ActionEvent event) {
        JButton button = (JButton) event.getSource();
        System.out.println(button.getActionCommand() + " was performed.");
    }
}

另类

JButton 具有内置的助记符处理。您可以通过JButton#setMnemonic(int)指定助记符,其中参数为键码:

jButton1.setMnemonic(KeyEvent.VK_A);

这是在图形界面中处理热键的标准方法。只需按住 Alt 键(Windows),然后按您设置助记符的键。

【讨论】:

  • 非常感谢您的输入,我现在更改了代码,在初始化函数的开头添加了 addKeyListener(this) 行。现在 Jframe 再次显示,但实际的键侦听器似乎不起作用。如您所见,它设置为根据单击的按钮打印特定内容。但事实并非如此。
  • @rootsquaredtimes89 这是因为框架需要在焦点上才能调度事件,因为侦听器已添加到框架中。您可以在显示后拥有框架requestFocus,但是一旦您单击框架(例如单击按钮时),它就会失去焦点。我已经更新了答案
  • 将KeyListener 添加到按钮不会产生额外效果,因为按钮在获得焦点之前不会响应,键绑定是解决KeyListener 问题的正确解决方案,但是按钮有一个内置的功能可以做类似的工作
  • @MadProgrammer 更新了我的答案。不要以为他会喜欢助记符,尽管我会在我的回答中包含它
  • @VinceEmigh 需要更多上下文来确定 OP 试图解决的问题,但如果它为他们节省了大量不必要的时间和精力,那么值得一提的是,这就是在大多数情况下,用户会“期待”
【解决方案2】:

键事件仅被分派给具有焦点的组件。你没有发布整个代码,但我猜焦点是你添加到框架的按钮,所以按钮获取 KeyEvent。

不确定您要使用 KeyListener 做什么。您无法通过查看 KeyEvent 中键入的字符来判断单击了哪个按钮。

如果您想知道点击了哪个按钮,则需要为每个按钮添加一个ActionListener。阅读 How to Use Buttons 上的 Swing 教程部分,了解更多信息和示例。

【讨论】:

    猜你喜欢
    • 2014-06-04
    • 2012-06-07
    • 1970-01-01
    • 1970-01-01
    • 2012-05-30
    • 1970-01-01
    • 1970-01-01
    • 2013-03-29
    相关资源
    最近更新 更多