简体   繁体   English

如果JTextField中有任何输入,则KeyListener不响应

[英]KeyListener does not respond if there is any input in JTextField

I develop a simple MVC Calculator app. 我开发了一个简单的MVC Calculator应用程序。 I decided to add some functionality by implementing KeyListener in CalculatorView. 我决定通过在CalculatorView中实现KeyListener来添加一些功能。 But this KeyListener only responds when there is no input in JTextField (before any input was made by pushing GUI buttons) or it responds when I press "ESC". 但是,此KeyListener仅在JTextField中没有输入时才响应(在通过按GUI按钮进行任何输入之前),或者在我按“ ESC”时响应。 I know some people here advice to use KeyBindings instead of KeyListener, but then I need to have 12 KeyBindings in my code (10 for numbers, 1 for ESC and 1 for "." character). 我知道这里有人建议使用KeyBindings代替KeyListener,但是我的代码中需要有12个KeyBindings(数字10个,ESC 1个和“。”字符1个)。 Is there any way to make KeyListener to work properly in my app? 有什么方法可以使KeyListener在我的应用中正常工作?

And here is the code: 这是代码:

/**
 *
 * @author Kate Nezdoly
 */
public class CalculatorView implements ActionListener, KeyListener {   

private JButton[] operButtons = new JButton[13];
private JButton[] numberButtons = new JButton[12];
private String[] operators = {"C", "(", ")", "+", "-", "*", "/", "^", "cos", "sin",
    "tan", "sqrt"};
private String[] numbers = {"1", "2", "3", "4", "5", "6", "7", "8",
    "9", "0", ".", "="};

public CalculatorView() {
    try {
        UIManager.setLookAndFeel(
                UIManager.getSystemLookAndFeelClassName());
    } catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
        System.err.println(e.getMessage());
    }

    createAndShowGUI();
}
private JTextField input;
private boolean decimal = true;

private JPanel createContentPane() {
    JPanel totalGUI = new JPanel(new BorderLayout(12, 8));
    input = new JTextField("0.0", 18);
    input.addKeyListener(this);
    input.setEditable(false);
    input.setBackground(Color.white);
    input.setHorizontalAlignment(JTextField.RIGHT);

    JPanel action_buttons = new JPanel(new GridLayout(5, 2));

    operButtons[0] = new JButton(operators[0]);
    action_buttons.add(operButtons[0]);

    for (int i = 1; i < operators.length; i++) {
        operButtons[i] = new JButton(operators[i]);
        operButtons[i].addActionListener(this);
        operButtons[i].setActionCommand(operators[i]);
        action_buttons.add(operButtons[i]);
    }

    JPanel number_buttons = new JPanel(new GridLayout(5, 2));

    for (int i = 0; i < numbers.length - 1; i++) {
        numberButtons[i] = new JButton(numbers[i]);
        numberButtons[i].addActionListener(this);
        numberButtons[i].setBackground(Color.lightGray);
        numberButtons[i].setActionCommand(numbers[i]);
        number_buttons.add(numberButtons[i]);
    }

    numberButtons[11] = new JButton(numbers[11]);
    number_buttons.add(numberButtons[11]);

    totalGUI.add(input, BorderLayout.PAGE_START);
    totalGUI.add(number_buttons, BorderLayout.CENTER);
    totalGUI.add(action_buttons, BorderLayout.LINE_END);

    totalGUI.setOpaque(true);
    return totalGUI;
}

private void createAndShowGUI() {
    JFrame frame = new JFrame("Calculator");

    frame.setContentPane(createContentPane());
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
    frame.setSize(300, 190);
    frame.setResizable(false);
}

public void actionPerformed(ActionEvent ae) {
    String temp = ae.getActionCommand();

    if (input.getText().equals("0.0")) {
        input.setText("");
    }

    if (temp.equals(".")) {
        if (decimal) {
            decimal = false;
            input.setText(input.getText() + "" + temp);
        }
    } 
    else {
        input.setText(input.getText() + "" + temp);
    }
}

public void buttonActionListeners(ActionListener al) {
    //add "=" action listener
    numberButtons[11].setActionCommand(numbers[11]);
    numberButtons[11].addActionListener(al);

    //add "C" action listener
    operButtons[0].setActionCommand(operators[0]);
    operButtons[0].addActionListener(al);

}

// Gets the text from the Text Box and converts it into a Double.
public String getFieldText() {
    return input.getText();
}

// Sets the text displayed on the Text Box.
public void setFieldText(String message) {
    input.setText("" + message);
    decimal = true;
}    

@Override
public void keyTyped(KeyEvent e) {

}

@Override
public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == 27) {
        System.exit(0);
    } else if (e.getKeyCode() >= 48 && e.getKeyCode() <= 57) {
        if (input.getText().equals("0.0")) {
            setFieldText(String.valueOf(e.getKeyChar()));
        } else {
            setFieldText(input.getText() + e.getKeyChar());

        }
}
}

@Override
public void keyReleased(KeyEvent e) {

}


}

Controller class: 控制器类:

public class CalculatorController implements  ActionListener {

private CalculatorView view;    

public CalculatorController( CalculatorView view)   {  
    this.view = view;
    view.buttonActionListeners(this);
}

@Override
public void actionPerformed(ActionEvent e) {
    String action = e.getActionCommand();
    switch (action) {
        case "=":
            view.setFieldText(Parser.parse(view.getFieldText()));                
            break;
        case "C":
            view.setFieldText("0.0");
            break;
    }
}

public static void main(String args[]){
    CalculatorView calc = new CalculatorView();
    CalculatorController contr = new CalculatorController(calc);
  }

}

I think that there isn't any reason for implement KeyListener/KeyBinding , 我认为没有KeyListener/KeyBinding实施KeyListener/KeyBinding

1) add as ActionCommand to the JButtons example here 1) 在此处将作为ActionCommand添加到JButtons示例

private String[] numbers = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", ".", "="};

2) change JTextField to the JFormattedTextField with NumberInstance/Formatter , then there are alowed only Numbers and decimal separator, and no longer there reason for listening from KeyBoard by implement KeyListener/KeyBinding s nor parsing/testing for NumberInstance 2)使用NumberInstance/FormatterJTextField更改为JFormattedTextField ,然后只允许使用数字和小数分隔符,并且不再需要通过实现KeyListener/KeyBinding解析或测试NumberInstance来从KeyBoard进行监听的原因

3) if is there more than one that one JFormattedTextField (value could be imputed or pasted from ClipBoard) or for example JFormattedTextField and JTextArea (for showing previous calculations) then chaining these fiedls by using DocumentListener 3)如果一个JFormattedTextField (可以从ClipBoard插值或粘贴值)或者例如JFormattedTextFieldJTextArea (用于显示以前的计算)的值不止一个,则使用DocumentListener链接这些文件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM