我正在用javafx构建一个计算器,并且试图实现一个实用程序,用户可以在其中输入要计算的公式,而不是一一键入数字和运算。该应用程序应打开一个新窗口,用户可以键入公式,然后单击计算。然后,公式窗口应关闭,结果将显示在主计算器的显示屏中。
我在主控制器中创建了一个可以设置公式值的方法
public void returnFormula(String _formula)
,然后在第二阶段调用控制器。从那里,我计划实现正则表达式以计算公式并返回结果。目前,我只想返回公式作为概念证明。但是,当我尝试显示结果时,它是空白的;调试显示公式的值为null。如何正确地将此值传递回主控制器?
IDE:Netbeans 9.0
Java版本:1.8.0_211
主控制器:
public class FXMLDocumentController implements Initializable {
//FXML Items
@FXML
private Button clearBttn;
@FXML
private Button signBttn;
@FXML
private Button percentBttn;
@FXML
private Button divBttn;
@FXML
private Button seven;
@FXML
private Button eight;
@FXML
private Button nine;
@FXML
private Button multBttn;
@FXML
private Button four;
@FXML
private Button five;
@FXML
private Button six;
@FXML
private Button subBttn;
@FXML
private Button one;
@FXML
private Button two;
@FXML
private Button three;
@FXML
private Button addBttn;
@FXML
private Button zero;
@FXML
private Button decimalPnt;
@FXML
private Button equalBttn;
@FXML
private MenuItem aboutPress;
@FXML
private TextField display;
@FXML
private AnchorPane anchor;
//class variables
double temp, result;
String currentNum = "",
formula;
Operation currentOp;
boolean opPressed;
@FXML
private MenuItem binaryMI;
@FXML
private MenuItem hexMI;
@FXML
private MenuItem formulaMI;
@Override
public void initialize(URL url, ResourceBundle rb) {
anchor.setOnKeyPressed((KeyEvent ev) -> { //listerner for all relevant keys
switch(ev.getCode()){
case DIGIT0:
zero.fire();
break;
case DIGIT1:
one.fire();
break;
case DIGIT2:
two.fire();
break;
case DIGIT3:
three.fire();
break;
case DIGIT4:
four.fire();
break;
case DIGIT5:
five.fire();
break;
case DIGIT6:
six.fire();
break;
case DIGIT7:
seven.fire();
break;
case DIGIT8:
eight.fire();
break;
case DIGIT9:
nine.fire();
break;
case EQUALS:
case ENTER:
equalBttn.fire();
break;
case MINUS:
subBttn.fire();
break;
case PLUS:
addBttn.fire();
break;
case SLASH:
divBttn.fire();
break;
case ASTERISK:
multBttn.fire();
break;
case PERIOD:
decimalPnt.fire();
break;
}
});
}
//NUMBER BUTTONS
@FXML
private void press7(ActionEvent event) {
if(opPressed){
currentNum = "";
opPressed = false;
}
currentNum += '7';
updateDisplay(currentNum);
}
@FXML
private void press8(ActionEvent event){
if(opPressed){
currentNum = "";
opPressed = false;
}
currentNum += '8';
updateDisplay(currentNum);
}
@FXML
private void press9(ActionEvent event) {
if(opPressed){
currentNum = "";
opPressed = false;
}
currentNum += '9';
updateDisplay(currentNum);
}
@FXML
private void press4(ActionEvent event) {
if(opPressed){
currentNum = "";
opPressed = false;
}
currentNum += '4';
updateDisplay(currentNum);
}
@FXML
private void press5(ActionEvent event) {
if(opPressed){
currentNum = "";
opPressed = false;
}
currentNum += '5';
updateDisplay(currentNum);
}
@FXML
private void press6(ActionEvent event) {
if(opPressed){
currentNum = "";
opPressed = false;
}
currentNum += '6';
updateDisplay(currentNum);
}
@FXML
private void press1(ActionEvent event) {
if(opPressed){
currentNum = "";
opPressed = false;
}
currentNum += '1';
updateDisplay(currentNum);
}
@FXML
private void press2(ActionEvent event) {
if(opPressed){
currentNum = "";
opPressed = false;
}
currentNum += '2';
updateDisplay(currentNum);
}
@FXML
private void press3(ActionEvent event) {
if(opPressed){
currentNum = "";
opPressed = false;
}
currentNum += '3';
updateDisplay(currentNum);
}
@FXML
private void press0(ActionEvent event) {
if(opPressed){
currentNum = "";
opPressed = false;
}
currentNum += '0';
updateDisplay(currentNum);
}
//OPERATIONAL BUTTONS
//Clear calculator
@FXML
private void clearPress(ActionEvent event) {
currentNum = "";
updateDisplay(currentNum);
temp = 0;
result = 0;
}
//alternate sign button
@FXML
private void signPress(ActionEvent event) {
if(getNum() == 0)
return;
try{
currentNum = Double.toString(getNum() * -1);
updateDisplay(currentNum);
}catch(NumberFormatException e){
numberError();
}
}
//create percent out of number
@FXML
private void percentPress(ActionEvent event) {
try{
currentNum = Double.toString(getNum() * .01);
updateDisplay(currentNum);
}catch(NumberFormatException e){
numberError();
}
}
//period button
@FXML
private void decPress(ActionEvent event) {
if(display.getText().trim().isEmpty()){
currentNum = "0.";
updateDisplay(currentNum);
}
else{
currentNum += ".";
updateDisplay(currentNum);
}
}
//MATH BUTTONS
//MULTIPLY
@FXML
private void multPress(ActionEvent event) {
currentOp = Operation.MUL;
opCheck();
}
//DIVIDE
@FXML
private void divPress(ActionEvent event) {
currentOp = Operation.DIV;
opCheck();
}
//SUBTRACT
@FXML
private void subPress(ActionEvent event) {
currentOp = Operation.SUB;
opCheck();
}
//ADD
@FXML
private void addPress(ActionEvent event) {
currentOp = Operation.ADD;
opCheck();
}
//EQUALS
@FXML
private void equalPress(ActionEvent event) {
try{
result = currentOp.math(temp, getNum());
currentNum = "";
temp = 0;
updateDisplay(result);
}
catch(NumberFormatException e){
numberError();
}
}
//INTERNAL FUNCTIONS
//checks if it's currently in an operation state
private void opCheck(){
if(!opPressed){
opPressed = true;
temp = getNum();
}
else{
opPressed = false;
equalBttn.fire();
}
}
//complete a math operations
private void completeOp(Operation _op){
try{
result = currentOp.math(result, getNum());
currentNum = "";
temp = 0;
updateDisplay(result);
}catch(NumberFormatException e){
numberError();
}
}
//get the current number from the display
private double getNum(){
return Double.parseDouble(display.getText());
}
//OVERLOADED update display using string
public void updateDisplay(String _num){
display.setText(_num);
}
//OVERLOADED UPDATE DISPLAY USING DOUBLE
private void updateDisplay(Double _num){
updateDisplay(Double.toString(_num));
}
//function to call if a number occurs, resets the calculator and present an error
private void numberError(){
Alert alert = new Alert(Alert.AlertType.ERROR, "Error parsing number input, calculator has been reset.");
alert.showAndWait();
currentNum = "";
updateDisplay(currentNum);
temp = 0;
result = 0;
}
@FXML
private void binPressed(ActionEvent event) {
if(display.getText().trim().isEmpty()){
Alert alert = new Alert(Alert.AlertType.ERROR, "Nothing to convert.");
alert.showAndWait();
return;
}
currentNum = "";
temp = 0;
result = 0;
opPressed = true;
int bin = (int)getNum();
TextField text = new TextField(Integer.toBinaryString(bin));
Stage stage = new Stage();
stage.setTitle("Binary Value");
stage.setScene(new Scene(text, 250, 25));
text.setEditable(false);
stage.setResizable(false);
stage.show();
}
@FXML
private void hexPressed(ActionEvent event) {
if(display.getText().trim().isEmpty()){
Alert alert = new Alert(Alert.AlertType.ERROR, "Nothing to convert.");
alert.showAndWait();
return;
}
currentNum = "";
temp = 0;
result = 0;
opPressed = true;
TextField text = new TextField(Double.toHexString(getNum()));
Stage stage = new Stage();
stage.setTitle("Hexedecimal Value");
stage.setScene(new Scene(text, 250, 25));
text.setEditable(false);
stage.setResizable(false);
stage.show();
}
@FXML
private void formulaPressed(ActionEvent event) {
try{
FXMLLoader fxmlLoader = new FXMLLoader(this.getClass().getResource("/simplecalculator/FormulaInputFXML.fxml"));
Stage formStage = new Stage();
Parent root1 = (Parent) fxmlLoader.load();
formStage.setTitle("Formula Input");
formStage.setScene(new Scene(root1));
formStage.show();
}catch(IOException e){
e.printStackTrace();
}
}
public void returnFormula(String _formula) {
this.formula = _formula;
updateDisplay(this.formula);
}
}
主要FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>
<AnchorPane id="AnchorPane" fx:id="anchor" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="295.0" prefWidth="225.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="simplecalculator.FXMLDocumentController">
<children>
<GridPane alignment="CENTER" layoutY="175.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="225.0" prefWidth="225.0" AnchorPane.topAnchor="70.0">
<columnConstraints>
<ColumnConstraints halignment="CENTER" hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints halignment="CENTER" hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints halignment="CENTER" hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints halignment="CENTER" hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" valignment="CENTER" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" valignment="CENTER" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" valignment="CENTER" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" valignment="CENTER" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" valignment="CENTER" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Button fx:id="clearBttn" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#clearPress" prefHeight="45.0" prefWidth="55.0" text="C" textAlignment="CENTER">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="signBttn" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#signPress" prefHeight="45.0" prefWidth="55.0" text="+/−" textAlignment="CENTER" textOverrun="CLIP" GridPane.columnIndex="1">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="percentBttn" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#percentPress" prefHeight="45.0" prefWidth="55.0" text="\%" textAlignment="CENTER" GridPane.columnIndex="2">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="divBttn" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#divPress" prefHeight="45.0" prefWidth="55.0" text="÷" textAlignment="CENTER" GridPane.columnIndex="3">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="seven" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#press7" prefHeight="45.0" prefWidth="55.0" text="7" textAlignment="CENTER" GridPane.rowIndex="1">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="eight" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#press8" prefHeight="45.0" prefWidth="55.0" text="8" textAlignment="CENTER" GridPane.columnIndex="1" GridPane.rowIndex="1">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="nine" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#press9" prefHeight="45.0" prefWidth="55.0" text="9" textAlignment="CENTER" GridPane.columnIndex="2" GridPane.rowIndex="1">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="multBttn" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#multPress" prefHeight="45.0" prefWidth="55.0" text="X" textAlignment="CENTER" GridPane.columnIndex="3" GridPane.rowIndex="1">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="four" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#press4" prefHeight="45.0" prefWidth="55.0" text="4" textAlignment="CENTER" GridPane.rowIndex="2">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="five" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#press5" prefHeight="45.0" prefWidth="55.0" text="5" textAlignment="CENTER" GridPane.columnIndex="1" GridPane.rowIndex="2">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="six" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#press6" prefHeight="45.0" prefWidth="55.0" text="6" textAlignment="CENTER" GridPane.columnIndex="2" GridPane.rowIndex="2">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="subBttn" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#subPress" prefHeight="45.0" prefWidth="55.0" text="−" textAlignment="CENTER" GridPane.columnIndex="3" GridPane.rowIndex="2">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="one" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#press1" prefHeight="45.0" prefWidth="55.0" text="1" textAlignment="CENTER" GridPane.rowIndex="3">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="two" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#press2" prefHeight="45.0" prefWidth="55.0" text="2" textAlignment="CENTER" GridPane.columnIndex="1" GridPane.rowIndex="3">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="three" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#press3" prefHeight="45.0" prefWidth="55.0" text="3" textAlignment="CENTER" GridPane.columnIndex="2" GridPane.rowIndex="3">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="addBttn" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#addPress" prefHeight="45.0" prefWidth="55.0" text="+" textAlignment="CENTER" GridPane.columnIndex="3" GridPane.rowIndex="3">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="zero" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#press0" prefHeight="45.0" prefWidth="112.0" text="0" textAlignment="CENTER" GridPane.halignment="LEFT" GridPane.rowIndex="4">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="decimalPnt" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#decPress" prefHeight="45.0" prefWidth="55.0" text="." textAlignment="CENTER" GridPane.columnIndex="2" GridPane.rowIndex="4">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
<Button fx:id="equalBttn" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#equalPress" prefHeight="45.0" prefWidth="55.0" text="=" textAlignment="CENTER" GridPane.columnIndex="3" GridPane.rowIndex="4">
<font>
<Font name="Verdana" size="16.0" />
</font>
</Button>
</children>
</GridPane>
<MenuBar layoutY="2.0" prefHeight="25.0" prefWidth="225.0">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Save equation to file" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Tools">
<items>
<MenuItem fx:id="binaryMI" mnemonicParsing="false" onAction="#binPressed" text="Convert to Binary" />
<MenuItem fx:id="hexMI" mnemonicParsing="false" onAction="#hexPressed" text="Convert to Hex" />
<MenuItem fx:id="formulaMI" mnemonicParsing="false" onAction="#formulaPressed" text="Enter Formula" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem fx:id="aboutPress" mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
<TextField fx:id="display" layoutY="80.0" maxWidth="-Infinity" minWidth="-Infinity" prefHeight="45.0" prefWidth="225.0" AnchorPane.topAnchor="25.0" />
</children>
</AnchorPane>
公式输入的控制器:
public class FormulaInputFXMLController implements Initializable
{
@FXML
private TextField formulaField;
@FXML
private Button calcBttn;
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
@FXML
private void calcuatePressed(ActionEvent event) {
try{
FXMLLoader fxmlLoader = new FXMLLoader(this.getClass().getResource("/simplecalculator/FXMLDocument.fxml"));
fxmlLoader.load();
FXMLDocumentController controller = fxmlLoader.getController();
controller.returnFormula(formulaField.getText());
Stage stage = (Stage)calcBttn.getScene().getWindow();
stage.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
公式输入FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="75.0" prefWidth="350.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="simplecalculator.FormulaInputFXMLController">
<children>
<TitledPane animated="false" collapsible="false" focusTraversable="false" layoutX="74.0" layoutY="-65.0" prefHeight="75.0" prefWidth="350.0" text="Enter Formula Below:" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<HBox alignment="CENTER" layoutX="74.0" layoutY="-25.0" prefHeight="49.0" prefWidth="348.0" spacing="10.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<TextField fx:id="formulaField" prefHeight="25.0" prefWidth="250.0" promptText="ex. 18+32 * (9 / 12)..." />
<Button fx:id="calcBttn" mnemonicParsing="false" onAction="#calcuatePressed" text="Calculate" />
</children>
</HBox>
</children>
</AnchorPane>
</content>
</TitledPane>
</children>
</AnchorPane>
很抱歉,如果我发布了太多的代码,由于我的许多功能重叠,所以不能完全确定哪些信息可能与该问题无关。