Setting up KeyListeners using the MVC in java

2019-03-01 06:16发布

问题:

I am trying to make myself a calculator in Java. I figured it would be best to implement the MVC (model view controller) design for my code. I have some of the basics working, the calculator does actually work, the issue is i cannot figure out where i am going wrong with the implementation of listening to keys. At the moment i have the ability to click on the buttons using the action listener and updating the field with a numeric value and the buttons to add, subtract, multiply, divide and also to clear. So really the only thing on my mind at the moment is trying to allow the user (myself) the option to use the number pad on the keyboard to append values to the field, anyways here is my code.

This the view

    package Calculator;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionListener;
import java.awt.event.KeyListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;

public class CalcFrame extends JFrame{


    private Dimension d = new Dimension(300,300);
    JPanel panel1 = new JPanel();
    JPanel panel2 = new JPanel();
    JButton equals = new JButton("=");
    JButton addBtn = new JButton("+");
    JButton subtractBtn = new JButton("-");
    JButton multiplyBtn = new JButton("*");
    JButton divideBtn = new JButton("/");
    JTextArea field = new JTextArea(1,20);
    JButton numBtn[] = new JButton[11];
    String numTxt[] = {"0","1","2","3","4","5","6","7","8","9","C"}; 
    Color newColor = new Color(10,70,40);
    int x = 50, y = 0;
    public CalcFrame(){
        this.setSize(d);
        this.setResizable(false);
    //  frame.setVisible(true);
        this.setTitle("Marks Calculator");
        this.setIconImage(new ImageIcon(this.getClass().getResource("emblem.png")).getImage());

        for(int i = 0; i < numBtn.length; i++){
            numBtn[i] = new JButton(numTxt[i]);
            numBtn[i].setSize(50, 30);

        }
        for(int i = 0; i <numBtn.length; i++){
            numBtn[0].setLocation(10,180);
            numBtn[1].setLocation(10,140);
            numBtn[2].setLocation(65,140);
            numBtn[3].setLocation(120,140);
            numBtn[4].setLocation(175,140);
            numBtn[5].setLocation(10,100);
            numBtn[6].setLocation(65,100);
            numBtn[7].setLocation(120,100);
            numBtn[8].setLocation(175,100);
            numBtn[9].setLocation(10,60);
            numBtn[10].setLocation(175,20);
            panel2.add(numBtn[i]);

        }
        field.setLocation(10, 10);
        field.setSize(280,30);
        field.setEditable(false);
        field.setFocusable(true);
        panel1.setSize(300, 50);
        panel1.setLayout(null);
        this.add(panel1);

        panel2.setSize(300, 250);
        panel2.setBackground(newColor);
        panel2.setLocation(0, 51);
        panel2.setLayout(null);
        this.add(panel2);

        equals.setLocation(230,180);
        equals.setSize(50, 30);
        panel2.add(equals);


        addBtn.setLocation(230, 140);
        addBtn.setSize(50,30);      
        panel2.add(addBtn);

        subtractBtn.setLocation(230, 100);
        subtractBtn.setSize(50,30);     
        panel2.add(subtractBtn);

        multiplyBtn.setLocation(230, 60);
        multiplyBtn.setSize(50,30);     
        panel2.add(multiplyBtn);

        divideBtn.setLocation(230, 20);
        divideBtn.setSize(50,30);       
        panel2.add(divideBtn);


        panel1.add(field);
        this.setLocationRelativeTo(rootPane);
        this.setLayout(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


    }

    public void addKeyL(KeyListener keyp){
        addKeyListener(keyp);
    }

    public void addListener(ActionListener listener){



    addBtn.addActionListener(listener);
    subtractBtn.addActionListener(listener);
    equals.addActionListener(listener);
    multiplyBtn.addActionListener(listener);
    divideBtn.addActionListener(listener);

    for(int i = 0; i < numBtn.length; i++){
        numBtn[i].addActionListener(listener);
    }



    }

    public int getFieldText(){

        return Integer.parseInt(field.getText());
    }
public void setFieldText(){

        field.setText("");
    }
    public void setAnswer(int solution){

        field.setText(Integer.toString(solution));
    }

}

this is the model

package Calculator;

public class Calculations {

    private int total;

    public void addNumbers(int a, int b){

        total = a + b;
    }

    public void subtractNumbers(int a, int b){

        total = a - b;
    }

    public void multiplyNumbers(int a, int b){

        total = a * b;
    }

    public void divideNumbers(int a, int b){

        total = a / b;
    }
    public int getTotal(){
        return total;
    }

}

and this is the controller

package Calculator;

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

import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class KeyEvents{

    private boolean isAdd = false;
    private boolean isSubtract = false;
    private boolean isDivide = false;
    private boolean isMultiply = false;
    private CalcFrame view = new CalcFrame();
    private Calculations model = new Calculations();
    int a = 0, b = 0, answer;
    int counter = 0;
    public KeyEvents(CalcFrame view, Calculations model){
        this.view = view;
        this.model = model;

        this.view.addListener(new CalcListener());
        this.view.addKeyL(new CalcListener());
    }



    class CalcListener implements ActionListener, KeyListener{

        @Override
        public void actionPerformed(ActionEvent e) {

                if(e.getSource().equals(view.addBtn)){
                    a = view.getFieldText();
                    view.field.setText("");
                    isAdd = true;
                    isSubtract = false;
                    isDivide = false;
                    isMultiply = false;

                }   


                if(e.getSource().equals(view.numBtn[0])){
                     view.field.append("0");                     
                }

                if(e.getSource().equals(view.numBtn[1])){
                    view.field.append("1");                 
                }

                if(e.getSource().equals(view.numBtn[2])){
                    view.field.append("2");
                }

                if(e.getSource().equals(view.numBtn[3])){
                    view.field.append("3");
                }

                if(e.getSource().equals(view.numBtn[4])){
                    view.field.append("4");
                }

                if(e.getSource().equals(view.numBtn[5])){
                    view.field.append("5");
                }

                if(e.getSource().equals(view.numBtn[6])){
                    view.field.append("6");;
                }

                if(e.getSource().equals(view.numBtn[7])){
                    view.field.append("7");
                }

                if(e.getSource().equals(view.numBtn[8])){
                    view.field.append("8");
                }

                if(e.getSource().equals(view.numBtn[9])){
                    view.field.append("9");
                }
                if(e.getSource().equals(view.numBtn[10])){
                    view.field.setText("");
                }

                if(e.getSource().equals(view.subtractBtn)){
                    a = view.getFieldText();
                    view.field.setText("");
                    isAdd = false;
                    isSubtract = true;
                    isDivide = false;
                    isMultiply = false;
                }   

                if(e.getSource().equals(view.multiplyBtn)){
                    a = view.getFieldText();
                    view.field.setText("");
                    isAdd = false;
                    isSubtract = false;
                    isDivide = false;
                    isMultiply = true;
                }   

                if(e.getSource().equals(view.divideBtn)){
                    a = view.getFieldText();
                    view.field.setText("");
                    isAdd = false;
                    isSubtract = false;
                    isDivide = true;
                    isMultiply = false;
                }   

                if(e.getSource().equals(view.equals)){
                    b = view.getFieldText();

                    if(isAdd == true){
                        view.setFieldText();
                        model.addNumbers(a, b);             
                        view.setAnswer(model.getTotal());
                    }

                    if(isSubtract == true){
                        view.setFieldText();
                        model.subtractNumbers(a, b);
                        view.setAnswer(model.getTotal());
                    }

                    if(isMultiply == true){
                        view.setFieldText();
                        model.multiplyNumbers(a, b);
                        view.setAnswer(model.getTotal());
                    }

                    if(isDivide == true){
                        view.setFieldText();
                        model.divideNumbers(a, b);
                        view.setAnswer(model.getTotal());
                    }

            }
        }

        @Override
        public void keyTyped(KeyEvent e) {
            if(e.getSource().equals(KeyEvent.VK_0)){
                System.out.println("sjkdhlkj");
            }
            if(e.getSource().equals(KeyEvent.VK_1)){
                view.field.append("1");
            }
            if(e.getSource().equals(KeyEvent.VK_2)){
                view.field.append("2");
            }
            if(e.getSource().equals(KeyEvent.VK_3)){
                view.field.append("3");
            }
            if(e.getSource().equals(KeyEvent.VK_4)){
                view.field.append("4");
            }
            if(e.getSource().equals(KeyEvent.VK_5)){
                view.field.append("5");
            }
            if(e.getSource().equals(KeyEvent.VK_6)){
                view.field.append("6");
            }
            if(e.getSource().equals(KeyEvent.VK_7)){
                view.field.append("7");
            }
            if(e.getSource().equals(KeyEvent.VK_8)){
                view.field.append("8");
            }
            if(e.getSource().equals(KeyEvent.VK_9)){
                view.field.append("9");
            }

        }

        @Override
        public void keyPressed(KeyEvent e) {
            if(e.getSource().equals(KeyEvent.VK_0)){
                System.out.println("sjkdhlkj");
            }
            if(e.getSource().equals(KeyEvent.VK_1)){
                view.field.append("1");
            }
            if(e.getSource().equals(KeyEvent.VK_2)){
                view.field.append("2");
            }
            if(e.getSource().equals(KeyEvent.VK_3)){
                view.field.append("3");
            }
            if(e.getSource().equals(KeyEvent.VK_4)){
                view.field.append("4");
            }
            if(e.getSource().equals(KeyEvent.VK_5)){
                view.field.append("5");
            }
            if(e.getSource().equals(KeyEvent.VK_6)){
                view.field.append("6");
            }
            if(e.getSource().equals(KeyEvent.VK_7)){
                view.field.append("7");
            }
            if(e.getSource().equals(KeyEvent.VK_8)){
                view.field.append("8");
            }
            if(e.getSource().equals(KeyEvent.VK_9)){
                view.field.append("9");
            }

        }

        @Override
        public void keyReleased(KeyEvent e) {
            if(e.getSource().equals(KeyEvent.VK_0)){
                System.out.println("sjkdhlkj");
            }
            if(e.getSource().equals(KeyEvent.VK_1)){
                view.field.append("1");
            }
            if(e.getSource().equals(KeyEvent.VK_2)){
                view.field.append("2");
            }
            if(e.getSource().equals(KeyEvent.VK_3)){
                view.field.append("3");
            }
            if(e.getSource().equals(KeyEvent.VK_4)){
                view.field.append("4");
            }
            if(e.getSource().equals(KeyEvent.VK_5)){
                view.field.append("5");
            }
            if(e.getSource().equals(KeyEvent.VK_6)){
                view.field.append("6");
            }
            if(e.getSource().equals(KeyEvent.VK_7)){
                view.field.append("7");
            }
            if(e.getSource().equals(KeyEvent.VK_8)){
                view.field.append("8");
            }
            if(e.getSource().equals(KeyEvent.VK_9)){
                view.field.append("9");
            }           
        }
    }   
}

the tl;dr of this is, i am unable to get keyListener to work correctly, i have tried assigning the keyListener to the field, panel1, panel2 and this. seperately. Assistance is appreciated as always.

~UPDATE~ I decided to give GitHub a try and have just put my code up on to it. I hope it would make my code easier to understand or even forkable so a person can mess around with it. https://github.com/niroshido/TestCalculator/tree/master/Calculator

回答1:

Use Key Bindings. A simple example:

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

public class CalculatorPanel extends JPanel
{
    private JTextField display;

    public CalculatorPanel()
    {
        Action numberAction = new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                display.setCaretPosition( display.getDocument().getLength() );
                display.replaceSelection(e.getActionCommand());
            }
        };

        setLayout( new BorderLayout() );

        display = new JTextField();
        display.setEditable( false );
        display.setHorizontalAlignment(JTextField.RIGHT);
        add(display, BorderLayout.NORTH);

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout( new GridLayout(0, 5) );
        add(buttonPanel, BorderLayout.CENTER);

        for (int i = 0; i < 10; i++)
        {
            String text = String.valueOf(i);
            JButton button = new JButton( text );
            button.addActionListener( numberAction );
            button.setBorder( new LineBorder(Color.BLACK) );
            button.setPreferredSize( new Dimension(50, 50) );
            buttonPanel.add( button );

            KeyStroke pressed = KeyStroke.getKeyStroke(text);
            InputMap inputMap = button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
            inputMap.put(pressed, text);
            button.getActionMap().put(text, numberAction);
        }
    }

    private static void createAndShowUI()
    {
//      UIManager.put("Button.margin", new Insets(10, 10, 10, 10) );

        JFrame frame = new JFrame("Calculator Panel");
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.add( new CalculatorPanel() );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}


回答2:

You either need to make sure that whatever component you're adding the KeyListener to has the focus, or you should use key bindings instead.