文本框中的KeyListener在按Enter键时无法触发

6
我正在尝试在Java中制作一个程序,可以将华氏温度转换为摄氏温度。在程序中我有2个标签和1个输入用的文本框。我希望当用户输入温度并按下Enter键时,立即进行温度转换。为此,我在文本框中添加了一个按键监听器,但是它不起作用。当我按下Enter键时,监听器根本没有触发。

以下是我的代码:

public class TempConv extends JFrame{

private JLabel info;
private JLabel result;
private JTextField input;
private String outcome;

public TempConv(){

    super("Temperature Converter");
    setLayout(new BorderLayout());

    info = new JLabel("Enter Fahrenheit Temperature");
    add(info, BorderLayout.NORTH);

    input = new JTextField(12);
    add(input, BorderLayout.CENTER);

    result  = new JLabel("Temperature in Celcius is: " + outcome);
    add(result, BorderLayout.SOUTH);

    input.addKeyListener(
            new KeyListener(){

                public void keyPressed(KeyEvent e){

                    if(e.getKeyChar() == KeyEvent.VK_ENTER){

                        outcome = input.getText();
                    }       
                }
            }
        );
}

public static void main(String[] args) {


    TempConv ftc = new TempConv();
    ftc.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    ftc.setLocationRelativeTo(null);
    ftc.setSize(370, 100);
    ftc.setVisible(true);


}

}

编辑:它可以使用ActionListener,但我需要使用匿名类来完成。如果没有匿名类,则会在Enter键按下时触发。


2
事件在事件链的上游被消耗掉了,因此它从未到达过你这里,最好使用键绑定 - 实际上,对于你要做的事情,最好使用ActionListener - 这就是它的设计目的 - 记住,对于每个平台,[Enter]并不总是“接受”键 ;) - MadProgrammer
2
有关平台无关性而言,当用户触发该平台的“接受”操作时,ActionListener 将被触发。恰巧对于大多数平台来说,这是 [Enter] 键。这重要吗? - MadProgrammer
在这种情况下,程序只应在用户按下回车键时运行。我尝试使用ActionListener,但这导致我使用KeyListener来监听键动作。我错了吗? - Miral
1
“我错了吗?” 是的...也不是。KeyListener对于您尝试实现的内容来说太低级了。如果您真的想要监视[Enter]键,那么您将不得不替换文本字段正在使用的键绑定。然而,这将改变应用程序在其他平台上的工作方式,因此需要使用ActionListener。这允许外观和感觉决定在什么条件下触发ActionListener。在大多数平台下,这是[Enter]键... - MadProgrammer
1
嗯..我明白你的意思了。那我就专注于ActionListener吧。 - Miral
显示剩余2条评论
5个回答

5
尝试使用e.getKeyCode()而不是e.getKeyChar()。常量KeyEvent.VK_ENTER是一个整数,而不是一个字符。
换句话说:
if(e.getKeyCode() == KeyEvent.VK_ENTER){
      outcome = input.getText();
}

替代,而不是
if(e.getKeyChar() == KeyEvent.VK_ENTER){
      outcome = input.getText();
}

不错的建议,但是,“当我按下回车键时,监听器根本没有触发”——[Enter]键被事件链中更高级别的组件所消耗,意味着监听器从未触发——[Enter]键被文本字段用于其他用途并被消耗了。 - MadProgrammer
这是真的,尽管我认为他们正在判断听众是否会触发,以及if语句是否实际导致输出被打印。也许我不应该做出这样的假设... - Sinkingpoint
1
就像我说的那样,这是一个不错的建议,但对于当前的情况并没有帮助,很抱歉。这是 OP 未来需要考虑的事情。 - MadProgrammer

1
首先,您需要实现KeyListener中的所有方法。您尚未实现keyTyped和keyReleased。另一件事是,您应该检查键代码而不是键字符,因为“Enter”字符不可见,所以最好检查键代码是否等于KeyEvent.VK_ENTER。最后一件事是,当您按下Enter键时,您更新了outcome String变量,但没有在任何地方显示它,因此您需要在result JLabel上设置文本。您还忘记了进行转换。我的解释可能会让人困惑,但以下是代码:
import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;

public class TempConv extends JFrame{

private JLabel info;
private JLabel result;
private JTextField input;
private String outcome;

public TempConv(){

    super("Temperature Converter");
    setLayout(new BorderLayout());

    info = new JLabel("Enter Fahrenheit Temperature");
    add(info, BorderLayout.NORTH);

    input = new JTextField(12);
    add(input, BorderLayout.CENTER);

    result  = new JLabel("Temperature in Celcius is: " + outcome);
    add(result, BorderLayout.SOUTH);

    input.addKeyListener(
            new KeyListener(){

                @Override
                public void keyPressed(KeyEvent e){

                    if(e.getKeyCode() == KeyEvent.VK_ENTER){
                        outcome = input.getText();
                        double celsius = (((Double.valueOf(outcome)) - 32) * 5 / 9 );
                        result.setText("Temperature in Celcius is: " + celsius);
                    }       
                }

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

                }

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

                }
            }
        );
}

public static void main(String[] args) {


    TempConv ftc = new TempConv();
    ftc.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    ftc.setLocationRelativeTo(null);
    ftc.setSize(370, 100);
    ftc.setVisible(true);


}

}

0

这应该可以工作

if (e.getKeyChar() == 10) {
    System.out.println("enter");
 }

输入ASCII代码为10,而KeyEvent.VK_ENTER返回回车符的13


0

按钮不需要 KeyListener(大多数情况下也不应该使用它们),它们使用 ActionListener 来响应所有激活事件,包括 Enter、鼠标单击和键盘快捷键,这是一个更简化的 API。

有关更多详细信息,请参见 如何使用按钮、复选框和单选按钮如何编写操作监听器如何使用操作

您还可以将按钮设置为“默认”按钮,当未聚焦时可以激活它(只要当前聚焦的组件不使用/消耗 Enter 键)。

查看 JRootPane#setDefaultButton如何使用根面板 以获取更多细节


0
晚了点回答,但我尝试了一下问题中的代码,KeyPressed确实触发了,但因为JLabel没有更新,你就认为KeyEvent没有被触发。

紧接着

outcome = input.getText(); 

添加

result.setText("Temperature in Celcius is: " + outcome);

这样标签就会自动更新。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接