Проблема с уравнениями в калькуляторе JavaFX - PullRequest
1 голос
/ 08 июля 2019

У меня проблема с моим калькулятором JavaFX / Java.Когда я ввожу уравнение, оно (калькулятор) работает нормально, и ответ тоже правильный.Но когда я нажимаю / ввод в другую операцию и другой номер после этого, результат / сумма / и т.д.не будет правильным, если оператор, который я нажал / набрал, не будет таким же, как раньше.Вот пример:

работает: 2 + 6 = 8 + 2 = 10

не работает: 2 + 6 = 8 - 2 = 10

работает: 6x 2 = 12 x 2 = 26

не работает: 6 x 2 = 12 ÷ 2 = 26

Мне было интересно, можно ли как-нибудь это исправить.

Вот мой класс контроллера FXML:

package calculator;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.KeyCode;
import javafx.stage.Stage;
import java.lang.Math;

public class Calculator implements Initializable {

    double data = 0d;
    int operation = -1;
    private boolean start = false;

    @FXML
    private Label display;

    @FXML
    private Button two;

    @FXML
    private Button five;

    @FXML
    private Button four;

    @FXML
    private Button three;

    @FXML
    private Button one;

    @FXML
    private Button six;

    @FXML
    private Button seven;

    @FXML
    private Button multi;

    @FXML
    private Button add;

    @FXML
    private Button divide;

    @FXML
    private Button minus;

    @FXML
    private Button equals;

    @FXML
    private Button clear;

    @FXML
    private Button zero;

    @FXML
    private Button nine;

    @FXML
    private Button eight;

    @FXML
    void handleButtonAction(ActionEvent event) {

        if(start)
        {
            display.setText("");
            start = false;
        }

        if(event.getSource() == one)
        {
            display.setText(display.getText() + "1");
        }
        else if(event.getSource() == two)
        {
            display.setText(display.getText() + "2");
        }
        else if(event.getSource() == three)
        {
            display.setText(display.getText() + "3");
        }
        else if(event.getSource() == four)
        {
            display.setText(display.getText() + "4");
        }
        else if(event.getSource() == five)
        {
            display.setText(display.getText() + "5");
        }
        else if(event.getSource() == six)
        {
            display.setText(display.getText() + "6");
        }
        else if(event.getSource() == seven)
        {
            display.setText(display.getText() + "7");
        }
        else if(event.getSource() == eight)
        {
            display.setText(display.getText() + "8");
        }
        else if(event.getSource() == nine)
        {
            display.setText(display.getText() + "9");
        }
        else if(event.getSource() == zero)
        {
            display.setText(display.getText() + "0");
        }
        else if(event.getSource() == clear)
        {
            display.setText("");
        } 
        else if(event.getSource() == add)
        {
            data = Float.parseFloat(display.getText());
            operation = 1;
            display.setText("");
        }
        else if(event.getSource() == minus)
        {
            data = Float.parseFloat(display.getText());
            operation = 2;
            display.setText("");
        }
        else if(event.getSource() == multi)
        {
            data = Float.parseFloat(display.getText());
            operation = 3;
            display.setText("");
        }
        else if(event.getSource() == divide)
        {
            data = Float.parseFloat(display.getText());
            operation = 4;
            display.setText("");
        }
        else if(event.getSource() == equals)
        {
            Float secondOperand = Float.parseFloat(display.getText());
            switch(operation)
            {
                case 1: //Addition
                    Double ans = data + secondOperand;
                    display.setText(String.valueOf(ans));
                    //data = ans;
                    break;
                case 2: //Subtraction
                    ans = data - secondOperand;
                    display.setText(String.valueOf(ans));
                    //data = ans;
                    break;
                case 3: //Multiplication
                    ans = data * secondOperand;
                    display.setText(String.valueOf(ans));
                    //data = ans;
                    break;
                case 4: //Division
                    ans = 0d;
                    try{
                    ans = data / secondOperand;
                    }catch(Exception ex){display.setText("Error");}
                    display.setText(String.valueOf(ans));
                    //data = ans;
                    break;
            }
            if(event.getSource() != divide && event.getSource() != add && event.getSource() != multi && event.getSource() != minus)
            {
                start = true;
            }
        }

    }

@FXML
    private void send2sceneconver(ActionEvent event) throws Exception{
        Parent rootBMI = FXMLLoader.load(getClass().getResource("ConversionCal.fxml"));

        Scene scene2 = new Scene(rootBMI);
        Stage calS = (Stage) ((Node) event.getSource()).getScene().getWindow();

        calS.setScene(scene2);
        calS.show();
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }  

}

Буду признателен за любую помощь.

Ответы [ 3 ]

3 голосов
/ 08 июля 2019

Так что я не совсем уверен, почему это там, но проблема с этим, если оценка

    if(start)
    {
        display.setText("");
        start = false;
    }

Я проверил его с вашими работами против не работает уравнения и все, кажется, в порядке. Причиной, которая его сломала, была перезагрузка дисплея при выполнении следующей операции, поэтому при просмотре он выглядит хорошо, но данные очищаются при попытке выполнить операцию. так что у него не было последних данных, чтобы извлечь из. Я закомментировал это, и остальные, кажется, работают, вот мой класс для проверки

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.stage.Stage;

import java.net.URL;
import java.util.ResourceBundle;


public class Calculator implements Initializable {

    double data = 0d;
    int operation = -1;
    private boolean start = false;

    @FXML
    private Label display;

    @FXML
    private Button two;

    @FXML
    private Button five;

    @FXML
    private Button four;

    @FXML
    private Button three;

    @FXML
    private Button one;

    @FXML
    private Button six;

    @FXML
    private Button seven;

    @FXML
    private Button multi;

    @FXML
    private Button add;

    @FXML
    private Button divide;

    @FXML
    private Button minus;

    @FXML
    private Button equals;

    @FXML
    private Button clear;

    @FXML
    private Button zero;

    @FXML
    private Button nine;

    @FXML
    private Button eight;

    @FXML
    void handleButtonAction(ActionEvent event) {

//        if(start)
//        {
//            display.setText("");
//            start = false;
//        }

        if(event.getSource() == one)
        {
            display.setText(display.getText() + "1");
        }
        else if(event.getSource() == two)
        {
            display.setText(display.getText() + "2");
        }
        else if(event.getSource() == three)
        {
            display.setText(display.getText() + "3");
        }
        else if(event.getSource() == four)
        {
            display.setText(display.getText() + "4");
        }
        else if(event.getSource() == five)
        {
            display.setText(display.getText() + "5");
        }
        else if(event.getSource() == six)
        {
            display.setText(display.getText() + "6");
        }
        else if(event.getSource() == seven)
        {
            display.setText(display.getText() + "7");
        }
        else if(event.getSource() == eight)
        {
            display.setText(display.getText() + "8");
        }
        else if(event.getSource() == nine)
        {
            display.setText(display.getText() + "9");
        }
        else if(event.getSource() == zero)
        {
            display.setText(display.getText() + "0");
        }
        else if(event.getSource() == clear)
        {
            display.setText("");
        }
        else if(event.getSource() == add)
        {
            data = Float.parseFloat(display.getText());
            operation = 1;
            display.setText("");
        }
        else if(event.getSource() == minus)
        {
            data = Float.parseFloat(display.getText());
            operation = 2;
            display.setText("");
        }
        else if(event.getSource() == multi)
        {
            data = Float.parseFloat(display.getText());
            operation = 3;
            display.setText("");
        }
        else if(event.getSource() == divide)
        {
            data = Float.parseFloat(display.getText());
            operation = 4;
            display.setText("");
        }
        else if(event.getSource() == equals)
        {
            Float secondOperand = Float.parseFloat(display.getText());
            switch(operation)
            {
                case 1: //Addition
                    Double ans = data + secondOperand;
                    display.setText(String.valueOf(ans));
                    //data = ans;
                    break;
                case 2: //Subtraction
                    ans = data - secondOperand;
                    display.setText(String.valueOf(ans));
                    //data = ans;
                    break;
                case 3: //Multiplication
                    ans = data * secondOperand;
                    display.setText(String.valueOf(ans));
                    //data = ans;
                    break;
                case 4: //Division
                    ans = 0d;
                    try{
                        ans = data / secondOperand;
                    }catch(Exception ex){display.setText("Error");}
                    display.setText(String.valueOf(ans));
                    //data = ans;
                    break;
            }
//            if(event.getSource() != divide && event.getSource() != add && event.getSource() != multi && event.getSource() != minus)
//            {
//                start = true;
//            }
        }
    }

    @FXML
    private void send2sceneconver(ActionEvent event) throws Exception{
        Parent rootBMI = FXMLLoader.load(getClass().getResource("ConversionCal.fxml"));

        Scene scene2 = new Scene(rootBMI);
        Stage calS = (Stage) ((Node) event.getSource()).getScene().getWindow();

        calS.setScene(scene2);
        calS.show();
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }
}

Также отметьте, что вы можете удалить implements Initializable, если вы его не используете

2 голосов
/ 08 июля 2019

Вы делаете следующее для нажатия кнопки equals

else if(event.getSource() == equals)
{
    ...
    if(event.getSource() != divide && event.getSource() != add && event.getSource() != multi && event.getSource() != minus)
    {
        start = true;
    }
}

Поскольку source - это equals, а не все остальные, вы всегда устанавливаете start на true, что при нажатии следующей кнопки заменяет содержимое display пустой строкой:

if(start)
{
    display.setText("");
    start = false;
}

В результате NumberFormatException будет брошено при следующем вызове

data = Float.parseFloat(display.getText());

Поскольку присвоение полю operation происходит после этого вызова, нажатие кнопки оператора сразу после нажатия equals не приводит к обновлению значения поля, и старый оператор всегда сохраняется.

Вместо этого вам нужно ввести поле, сообщающее вам, доступен ли первый операнд или должен быть проанализирован.

private final Set<Button> numbers = new HashSet<>();
private final Map<Button, Integer> operators = new HashMap<>();

@Override
public void initialize(URL url, ResourceBundle rb) {
    numbers.addAll(Arrays.asList(zero, one, two, three, four, five, six, seven, eight, nine));
    operators.put(add, 1);
    operators.put(minus, 2);
    operators.put(multi, 3);
    operators.put(divide, 4);
}

private double data;
private boolean dataAvailable = false;

@FXML
private void handleButtonAction(ActionEvent event) {
    Button source = (Button) event.getSource();

    if (source == clear) {
        dataAvailable = false;
        display.setText("");
        operation = 0;
    } else if (source == equals) {
        double secondOperand;
        try {
            secondOperand = Double.parseDouble(display.getText());
        } catch (NumberFormatException ex) {
            return; // only continue, if parsing is successful
        }
        double result;
        switch (operation) {
            case 1: //Addition
                result = data + secondOperand;
                break;
            case 2: //Subtraction
                result = data - secondOperand;
                break;
            case 3: //Multiplication
                result = data * secondOperand;
                break;
            case 4: //Division
                double res = data / secondOperand;
                if (Double.isFinite(res)) {
                    result = res;
                } else {
                    // TODO: division by zero
                }
                break;
            default:
                return; // ignore press, if operand is not set yet
        }
        display.setText(Double.toString(result));
        operation = 0;
        data = result;
        dataAvailable = true;
    } else if (numbers.contains(source)) {
        if (!dataAvailable) { // just ignore input, if = gave us the first operand
            display.setText(display.getText() + source.getText());
        }
    } else {
        Integer op = operators.get(source);
        if (op != null) {
            if (!dataAvailable) {
                try {
                    data = Double.parseDouble(display.getText());
                } catch (NumberFormatException ex) {
                    return; // do nothing on invalid input
                }
            } else {
                dataAvailable = false;
            }
            display.setText("");
            operation = op;
        }
    }
}
0 голосов
/ 14 июля 2019

Я также нашел другой способ объявить [операцию =] перед [данными =], например:

        else if(event.getSource() == divide)
        {
            operation = -1;
            operation = 4;
            data = Float.parseFloat(display.getText());
            display.setText("");
            dot.setDisable(false);
        }
...