我正在制作一个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);
}
}
Model.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>
答案 0 :(得分:0)
您的主要问题源于此处未处理的NumberFormatException:
output.setText(String.valueOf(model.calculate(number1, Long.parseLong(output.getText()), operator)));
由于您的设计需要等于启动实际计算,因此它还假设存在第二个数字。所以这可以通过以下输入重新创建:
5x²=(作为第二个值未提供,正在为第二个值解析空字符串)
快速修复就是用以下内容替换该行:
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。它用于将中缀符号方程解析为它们的后缀等价物,以便于计算。在过去亲自使用它来创建自定义科学计算器,它将允许您为自己的计算器添加其他功能。实现的主要好处是能够使用其他运算符输入更复杂的方程式。
即使你最终没有使用它,知道/了解
也是一个有趣的算法