【问题标题】:JavaFX Calculator - How do I add a square and square root function?JavaFX Calculator - 如何添加平方和平方根函数?
【发布时间】:2016-06-06 20:39:14
【问题描述】:

我正在制作一个 JavaFX 计算器。我正在尝试开发平方和平方根函数,但我很困惑在 Controller.java 中为该方法编写什么。我不确定它们是否工作正常,如果我点击它们,它们什么也不会返回。我想,“好吧,价值存储了吗?”我尝试将 0 添加到它以查看是否有结果和错误。

App.java:

package com.honors.calc;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class App extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("ui.fxml"));

        primaryStage.setScene(new Scene(root));
        primaryStage.show();

    }

    public static void main(String[] args) {
        launch(args);

    }

}

模型.java:

package com.honors.calc;

public class Model {

    public long calculate(long number1, long number2, String operator) {
        switch (operator) {
            case "+":
                return number1 + number2;
            case "-":
                return number1 - number2;
            case "*":
                return number1 * number2;
            case "/":
                if (number2 == 0)
                    return 0;

                return number1 / number2;
            case "C":
                number1 = 0;
                number2 = 0;
                return 0;
            case "CE":
                number2 = 0;
                return 0;
            case "x²":
                return number1 * number1;
            case "√":
                return (long) Math.sqrt(number1);
        }
        System.out.println("Unknown operator - " + operator);
        return 0;
    }
}

Controller.java:

package com.honors.calc;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.text.Text;

public class Controller {
    @FXML
    private Text output;

    private long number1 = 0;
    private String operator = "";
    private boolean start = true;

    private Model model = new Model();

    @FXML
    private void processNumpad(ActionEvent event) {
        if (start) {
            // clear screen
            output.setText("");
            start = false;
        }
        String value = ((Button)event.getSource()).getText();
        output.setText(output.getText() + value);
    }

    @FXML
    private void processOperator(ActionEvent event) {
        String value = ((Button)event.getSource()).getText();

        if(!"=".equals(value)) {
            if (!operator.isEmpty())
                return;

            operator = value;
            number1 = Long.parseLong(output.getText());
            output.setText("");
        } else {
            // calculation
            if (operator.isEmpty())
                return;

            output.setText(String.valueOf(model.calculate(number1, Long.parseLong(output.getText()), operator)));
            operator = "";
            // reset
            start = true;
        }
    }

    @FXML
    private void processClear(ActionEvent event) {
        output.setText("0");
    }

    @FXML
    private void processClearEntry(ActionEvent event) {
        output.setText("");
    }

    @FXML
    private void processSquare(ActionEvent event) {


    }

    @FXML
    private void processSquareRoot(ActionEvent event) {

    }
}

ui.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.net.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.beans.property.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.paint.Color?>

<VBox spacing="10" alignment="CENTER" prefWidth="300" prefHeight="320" fx:controller="com.honors.calc.Controller" xmlns:fx="http://javafx.com/fxml">
    <fx:define>
        <Font fx:id="FONT" size="18" />
    </fx:define>

    <StackPane alignment="CENTER">
        <Rectangle fill="TRANSPARENT" stroke="GRAY" width="230" height="50" />
        <Text fx:id="output" font="$FONT" />
    </StackPane>

    <HBox spacing="10" alignment="CENTER">
        <Button text="C" prefWidth="50" font="$FONT" onAction="#processClear" />
        <Button text="CE" prefWidth="50" font="$FONT" onAction="#processClearEntry" />
        <Button text="x²" prefWidth="50" font="$FONT" onAction="#processSquare" />
        <Button text="√" prefWidth="50" font="$FONT" onAction="#processSquareRoot" />
    </HBox>

    <HBox spacing="10" alignment="CENTER">
        <Button text="7" prefWidth="50" font="$FONT" onAction="#processNumpad" />
        <Button text="8" prefWidth="50" font="$FONT" onAction="#processNumpad" />
        <Button text="9" prefWidth="50" font="$FONT" onAction="#processNumpad" />
        <Button text="/" prefWidth="50" font="$FONT" onAction="#processOperator" />
    </HBox>

    <HBox spacing="10" alignment="CENTER">
        <Button text="4" prefWidth="50" font="$FONT" onAction="#processNumpad" />
        <Button text="5" prefWidth="50" font="$FONT" onAction="#processNumpad" />
        <Button text="6" prefWidth="50" font="$FONT" onAction="#processNumpad" />
        <Button text="*" prefWidth="50" font="$FONT" onAction="#processOperator" />
    </HBox>

    <HBox spacing="10" alignment="CENTER">
        <Button text="1" prefWidth="50" font="$FONT" onAction="#processNumpad" />
        <Button text="2" prefWidth="50" font="$FONT" onAction="#processNumpad" />
        <Button text="3" prefWidth="50" font="$FONT" onAction="#processNumpad" />
        <Button text="-" prefWidth="50" font="$FONT" onAction="#processOperator" />
    </HBox>

    <HBox spacing="10" alignment="CENTER">
        <Button text="0" prefWidth="110" font="$FONT" onAction="#processNumpad" />
        <Button text="=" prefWidth="50" font="$FONT" onAction="#processOperator" />
        <Button text="+" prefWidth="50" font="$FONT" onAction="#processOperator" />
    </HBox>

</VBox>

【问题讨论】:

  • 你为什么希望它做任何事情? processSquareprocessSquareRoot 函数完全为空。
  • @jewelsea 我想我有在 Model.java case "x²": return number1 * number1; case "√": return (long) Math.sqrt(number1); 中定义的语法,但问题是我不确定在方法中放什么。对于其他方法,我输入了output.setText("");,但这似乎不适合放入processSquareprocessSquareRoot

标签: java javafx


【解决方案1】:

您的主要问题源于此处未处理的NumberFormatException

output.setText(String.valueOf(model.calculate(number1, Long.parseLong(output.getText()), operator)));

由于您的设计需要一个等于来启动实际计算,因此它还假设将存在第二个数字。所以这是可以通过以下输入重新创建的:

5 x² =(由于未提供第二个值,因此正在为第二个值解析一个空字符串)

对此的快速修复是将该行替换为以下内容:

        long number2 = 0;
        try{
            number2 = Long.parseLong(output.getText());
        }catch (NumberFormatException nfe){
            System.out.println("Invalid value provided for second value");
        }
        output.setText(String.valueOf(model.calculate(number1, number2, operator)));

并更新您的 fxml:

<Button text="x²" prefWidth="50" font="$FONT" onAction="#processOperator" />
<Button text="√" prefWidth="50" font="$FONT" onAction="#processOperator" />

这样就不需要这些方法了:

    @FXML
    private void processSquare(ActionEvent event) {    
    }

    @FXML
    private void processSquareRoot(ActionEvent event) {    
    }

即使您要实现它们,它们也无法在不改进您的基础设计的情况下计算值,因为所需的操作和数字仅在您的 processOperator 方法中使用


作为旁注,我建议阅读Shunting Yard Algorithm。它用于将中缀符号方程解析为其后缀等效项,以便于计算。过去曾亲自使用它来创建自定义科学计算器,它可以让您为自己的计算器添加额外的功能。您实现的主要好处是能够使用其他运算符输入更复杂的方程。

即使你最终没有使用它,它也是一种有趣的算法,需要了解/注意

【讨论】:

    猜你喜欢
    • 2015-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多