插入小数点Java计算器GUI

时间:2018-06-04 19:29:16

标签: java javafx

我一直在搞清楚如何将一个小数位函数添加到我正在构建的非常简单的计算器中。我对makeDecimalButton函数的当前实现在运行时抛出错误。我不应该将小数解析为double吗?也许我应该使用BigDecimal?任何帮助表示赞赏。

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

import java.util.HashMap;
import java.util.Map;

public class Calculator extends Application {
    private static final String[][] template = { 
            { "7", "8", "9", "/" }, 
            { "4", "5", "6", "*" }, 
            { "1", "2", "3", "-" },
            { "0", "C", "=", "+", "." } };

    private final Map<String, Button> accelerators = new HashMap<>();

    private DoubleProperty stackValue = new SimpleDoubleProperty();
    private DoubleProperty value = new SimpleDoubleProperty();

    private enum Operation {
        NOOP, ADD, SUBTRACT, MULTIPLY, DIVIDE
    }

    private Operation curOp = Operation.NOOP;
    private Operation stackOp = Operation.NOOP;

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

    @Override
    public void start(Stage stage) {
        final TextField screen = createScreen();
        final TilePane buttons = createButtons();

        stage.setTitle("Calculator");
        stage.initStyle(StageStyle.UTILITY);
        stage.setResizable(false);
        stage.setScene(new Scene(createLayout(screen, buttons)));
        stage.show();
    }

    private VBox createLayout(TextField screen, TilePane buttons) {
        final VBox layout = new VBox(20);
        layout.setAlignment(Pos.CENTER);
        layout.setStyle("-fx-background-color: black; -fx-padding: 20; -fx-font-size: 20;");
        layout.getChildren().setAll(screen, buttons);
        handleAccelerators(layout);
        screen.prefWidthProperty().bind(buttons.widthProperty());
        return layout;
    }

    private void handleAccelerators(VBox layout) {
        layout.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent keyEvent) {
                Button activated = accelerators.get(keyEvent.getText());
                if (activated != null) {
                    activated.fire();
                }
            }
        });
    }

    private TextField createScreen() {
        final TextField screen = new TextField();
        screen.setStyle("-fx-background-color: white;");
        screen.setAlignment(Pos.CENTER_RIGHT);
        screen.setEditable(false);
        screen.textProperty().bind(Bindings.format("%f", value));
        return screen;
    }

    private TilePane createButtons() {
        TilePane buttons = new TilePane();
        buttons.setVgap(7);
        buttons.setHgap(7);
        buttons.setPrefColumns(template[0].length);
        for (String[] r : template) {
            for (String s : r) {
                buttons.getChildren().add(createButton(s));
            }
        }
        return buttons;
    }

    private Button createButton(final String s) {
        Button button = makeStandardButton(s);

        if (s.matches("[0-9]")) {
            makeNumericButton(s, button);
        } else {
            final ObjectProperty<Operation> triggerOp = determineOperand(s);
            if (triggerOp.get() != Operation.NOOP) {
                makeOperandButton(button, triggerOp);
            } else if ("C".equals(s)) {
                makeClearButton(button);
            } else if ("=".equals(s)) {
                makeEqualsButton(button);
            } else if (".".equals(s)) {
                makeDecimalButton(button);
            }
        }

        return button;
    }

    private void makeDecimalButton(Button button) {
        button.setStyle("-fx-base: mistyrose;");
        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                value.set(value.get() + Double.parseDouble("."));
            }
        }); 
    }

    private ObjectProperty<Operation> determineOperand(String s) {
        final ObjectProperty<Operation> triggerOp = new SimpleObjectProperty<>(Operation.NOOP);
        switch (s) {
        case "+":
            triggerOp.set(Operation.ADD);
            break;
        case "-":
            triggerOp.set(Operation.SUBTRACT);
            break;
        case "*":
            triggerOp.set(Operation.MULTIPLY);
            break;
        case "/":
            triggerOp.set(Operation.DIVIDE);
            break;
        }
        return triggerOp;
    }

    private void makeOperandButton(Button button, final ObjectProperty<Operation> triggerOp) {
        button.setStyle("-fx-base: lightgray;");
        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                curOp = triggerOp.get();
            }
        });
    }

    private Button makeStandardButton(String s) {
        Button button = new Button(s);
        button.setStyle("-fx-base: beige;");
        accelerators.put(s, button);
        button.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        return button;
    }

    private void makeNumericButton(final String s, Button button) {
        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                if (curOp == Operation.NOOP) {
                    value.set(value.get() * 10 + Integer.parseInt(s));
                } else {
                    stackValue.set(value.get());
                    value.set(Integer.parseInt(s));
                    stackOp = curOp;
                    curOp = Operation.NOOP;
                }
            }
        });
    }

    private void makeClearButton(Button button) {
        button.setStyle("-fx-base: mistyrose;");
        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                value.set(0);
            }
        });
    }

    private void makeEqualsButton(Button button) {
        button.setStyle("-fx-base: ghostwhite;");
        button.setOnAction(new EventHandler<ActionEvent>() {
            @SuppressWarnings("incomplete-switch")
            @Override
            public void handle(ActionEvent actionEvent) {
                switch (stackOp) {
                case ADD:
                    value.set(stackValue.get() + value.get());
                    break;
                case SUBTRACT:
                    value.set(stackValue.get() - value.get());
                    break;
                case MULTIPLY:
                    value.set(stackValue.get() * value.get());
                    break;
                case DIVIDE:
                    value.set(stackValue.get() / value.get());
                    break;
                }
            }
        });
    }
}

1 个答案:

答案 0 :(得分:0)

来自文档:

parseDouble(String s)
Returns a new double initialized to the value represented by the specified String, as performed by the valueOf method of class Double.

所以你试图从字符串&#34;中解析一个double。&#34;这不是有效的十进制数。