JavaFX第二弹——Create the Calculator GUI

Posted on 2021-12-02 20:08  Capterlliar  阅读(134)  评论(0编辑  收藏  举报

(又名应付作业第二弹——痛苦计算器)

0.效果图

            其实按下去的css调得蛮有动感的hhh

 

 

1.界面制作

这次界面写的,梦回小时候在4399上玩装饰大蛋糕。

背景是一个朴实无华的VBox,上面放一个朴实无华的HBox,下面是一个GridPane。具体就不写。

将HBox里东西向右靠齐:

textField.setAlignment(Pos.CENTER_RIGHT);

GridPane的网格顺序是和数组反着来的orz

好接下来美化一下。

试图用FX里自带的函数,然后,

BorderStroke borderStroke = new BorderStroke(Paint.valueOf("#8A2BE2"),
BorderStrokeStyle.DASHED, new CornerRadii(0), new BorderWidths(2));
Border border = new Border(borderStroke);

出来的结果-------->

 

bt.setEffect(new DropShadow());

 

册那。放弃挣扎,写css吧。

连接Java和css:

Application.setUserAgentStylesheet("CalculatorGUI.css");

这句放在start函数里。

VBox vBox=new VBox();
vBox.getStyleClass().add("vbox");
//CSS部分
.vbox{
    -fx-padding: 20 10 10 10;
    -fx-background-color:#009FCC;
}

给它起个名。

.button{
    -fx-alignment: center;
    -fx-background-color: #009FCC;
    -fx-background-radius: 0;
    -fx-text-fill: white;
    -fx-border-width: 0 2 2 0;
    -fx-border-color: black;
    -fx-border-style:solid;
    -fx-pref-height:40;
    -fx-pref-width:50;
}

这是不起名,所有Button都写这样的。

但是JavaFX的CSS和实际的CSS还是有点区别,可以参照官方文档写:点这里

 这是中文版的,不是很全,但会讲一下怎么写:戳这里

关于用什么颜色好看:我是色板

CSS动态状态:here

好可以绑定函数了。

3.动态

这次的动态绑定有点烦,毕竟后缀表达式中缀表达式也有那么几十行代码,就当复习数据结构了。

先搞简单的,加入数字。这里偷懒了,每次清空重来一遍。反正我也不输多长的式子,能跑就行()附带的好处就是不用清零键了。

(顺便一提本来想加个清零键点一下就会发出响亮的“归零!”那种,但面板上实在放lan不de下gai了就没弄hhh)

给等于号单独一个函数。为了能让屏幕上多出现一点不同的字符就抛个异常吧。(喂

    String[][] a={{"7","8","9","+"},
                {"4", "5", "6", "-"},
                {"1", "2", "3", "*"},
                {"0", ".", "=", "/"}};
    for(int i=0;i<4;i++){
            for(int j=0;j<4;j++){
                Button bt=new Button(a[i][j]);
                if(!a[i][j].equals("=")){
                    int x=i,y=j;
                    bt.setOnAction(actionEvent -> addToText(a[x][y]));
//注意这里不能直接写i和j,它不接受临时变量。
                }
                else {
                    bt.setOnAction(actionEvent -> {
                        try {
                            cal();
                        }
                        catch (Exception e) {
                            if(e instanceof MathException)
                                printError(e.toString());
//错误有两种,一是除以0这类数学错误,二是多输了符号啊什么的输入错误。多写了一个异常类区分一下。
                            else
                                printError("Input Error!");
                        }
                    });
                }
                gridPane.add(bt,j,i+1);
            }
        }
    private void cal() throws Exception{
        textField.getChildren().clear();
        textField.getChildren().add(new Label(calSuff()));
        pres="";
    }
    private void addToText(String s){
        pres+=s;
        textField.getChildren().clear();
        textField.getChildren().add(new Label(pres));
    }

两个处理函数。没错字符和文本框那里开了全局变量。说到文本框本来看作业要求,真的弄了个TextField,后来发现这玩意不仅一闪一闪的还没法动态添加。换HBox了,但变量名没改。

**到这里为止这个计算器除了不能算数以外没什么缺点啦**

开始处理String。输进来的是中缀表达式,转成后缀表达式,然后计算。好在这个计算器表面没有括号,可以少写一点。

具体看注释:

    private boolean isOperator(String op){
        return op.equals("+") || op.equals("-") || op.equals("*") || op.equals("/");
    }//判符号
    private int priority(String op){
        if(op.equals("*") || op.equals("/")){
            return 1;
        }else if(op.equals("+") || op.equals("-")){
            return 0;
        }
        return -1;
    }//判优先级
    private List<String> Suff(String exp) {
        Stack<String> opStack = new Stack<>();
        List<String> s=new LinkedList<>();
        StringBuilder temp = new StringBuilder();//因为可能有小数,所以不能一位一位读。先把两个符号之间的东西存下来,然后统一转Double
        for(int i=0;i<exp.length();i++){
            String item=String.valueOf(exp.charAt(i));
            if(isOperator(item)){
                if(temp.length()!=0) {
                    s.add(String.valueOf(temp));
                    temp.delete(0,temp.length());//也可以重新new一个啦,但是效率会差一点
                }
                if(opStack.isEmpty() ||priority(item) > priority(opStack.peek())){
                    opStack.push(item);
                }else {
                    while (!opStack.isEmpty()){
                        if(priority(item) <= priority(opStack.peek()))
                            s.add(opStack.pop());
                    }
                    opStack.push(item);
                }
            }
            else
                temp.append(item);
        }
//把剩下的东西都加进来
        s.add(String.valueOf(temp));
        while(!opStack.empty()){
            s.add(opStack.peek());
            opStack.pop();
        }
        return s;
    }
    private String calSuff() throws Exception{
        Stack<Double> stack=new Stack<>();
        List<String> ans=Suff(pres);
        for(String i:ans){
            if(i.equals("+")){
                Double x=stack.peek();stack.pop();
                Double y=stack.peek();stack.pop();
                stack.push(x+y);
            }
            else if(i.equals("-")){
                Double x=stack.peek();stack.pop();
                Double y=stack.peek();stack.pop();
                stack.push(y-x);
            }
            else if(i.equals("*")){
                Double x=stack.peek();stack.pop();
                Double y=stack.peek();stack.pop();
                stack.push(x*y);
            }
            else if(i.equals("/")){
                Double x=stack.peek();stack.pop();
                if(x==0)
                    throw new MathException("Error!The divisor can't be 0!");
                Double y=stack.peek();stack.pop();
                stack.push(y/x);
            }
            else{
                double temp=Double.parseDouble(i);
                stack.push(temp);
            }
        }
        String r=String.format("%.2f",stack.peek());
        return r;
    }
    private void cal() throws Exception{
        textField.getChildren().clear();
        textField.getChildren().add(new Label(calSuff()));
        pres="";
    }

到这里好像就写完了?那就这样吧。感谢您的观看(如果真的有人看的话

完整代码:

  1 import javafx.application.Application;
  2 import javafx.geometry.Pos;
  3 import javafx.scene.Scene;
  4 import javafx.scene.control.Button;
  5 import javafx.scene.control.Label;
  6 import javafx.scene.layout.*;
  7 import javafx.stage.Stage;
  8 
  9 import java.util.LinkedList;
 10 import java.util.List;
 11 import java.util.Stack;
 12 
 13 class MathException extends Exception{
 14     public MathException(String message){
 15         super(message);
 16     }
 17 }
 18 
 19 public class CalculatorGUI extends Application {
 20     HBox textField;
 21     String pres="";
 22     private void printError(String s){
 23         textField.getChildren().add(new Label(s));
 24         pres="";
 25     }
 26     private void addToText(String s){
 27         pres+=s;
 28         textField.getChildren().clear();
 29         textField.getChildren().add(new Label(pres));
 30     }
 31     private boolean isOperator(String op){
 32         return op.equals("+") || op.equals("-") || op.equals("*") || op.equals("/");
 33     }
 34     private int priority(String op){
 35         if(op.equals("*") || op.equals("/")){
 36             return 1;
 37         }else if(op.equals("+") || op.equals("-")){
 38             return 0;
 39         }
 40         return -1;
 41     }
 42     private List<String> Suff(String exp) {
 43         Stack<String> opStack = new Stack<>();
 44         List<String> s=new LinkedList<>();
 45         StringBuilder temp = new StringBuilder();
 46         for(int i=0;i<exp.length();i++){
 47             String item=String.valueOf(exp.charAt(i));
 48             if(isOperator(item)){
 49                 if(temp.length()!=0) {
 50                     s.add(String.valueOf(temp));
 51                     temp.delete(0,temp.length());
 52                 }
 53                 if(opStack.isEmpty() ||priority(item) > priority(opStack.peek())){
 54                     opStack.push(item);
 55                 }else {
 56                     while (!opStack.isEmpty()){
 57                         if(priority(item) <= priority(opStack.peek()))
 58                             s.add(opStack.pop());
 59                     }
 60                     opStack.push(item);
 61                 }
 62             }
 63             else
 64                 temp.append(item);
 65         }
 66         s.add(String.valueOf(temp));
 67         while(!opStack.empty()){
 68             s.add(opStack.peek());
 69             opStack.pop();
 70         }
 71         return s;
 72     }
 73     private String calSuff() throws Exception{
 74         Stack<Double> stack=new Stack<>();
 75         List<String> ans=Suff(pres);
 76         for(String i:ans){
 77             if(i.equals("+")){
 78                 Double x=stack.peek();stack.pop();
 79                 Double y=stack.peek();stack.pop();
 80                 stack.push(x+y);
 81             }
 82             else if(i.equals("-")){
 83                 Double x=stack.peek();stack.pop();
 84                 Double y=stack.peek();stack.pop();
 85                 stack.push(y-x);
 86             }
 87             else if(i.equals("*")){
 88                 Double x=stack.peek();stack.pop();
 89                 Double y=stack.peek();stack.pop();
 90                 stack.push(x*y);
 91             }
 92             else if(i.equals("/")){
 93                 Double x=stack.peek();stack.pop();
 94                 if(x==0)
 95                     throw new MathException("Error!The divisor can't be 0!");
 96                 Double y=stack.peek();stack.pop();
 97                 stack.push(y/x);
 98             }
 99             else{
100                 double temp=Double.parseDouble(i);
101                 stack.push(temp);
102             }
103         }
104         String r=String.format("%.2f",stack.peek());
105         return r;
106     }
107     private void cal() throws Exception{
108         textField.getChildren().clear();
109         textField.getChildren().add(new Label(calSuff()));
110         pres="";
111     }
112     private GridPane getGridPane(){
113         GridPane gridPane=new GridPane();
114         gridPane.getStyleClass().add("gridPane");
115         gridPane.setHgap(10);
116         gridPane.setVgap(10);
117         String[][] a={{"7","8","9","+"},
118                 {"4", "5", "6", "-"},
119                 {"1", "2", "3", "*"},
120                 {"0", ".", "=", "/"}};
121         for(int i=0;i<4;i++){
122             for(int j=0;j<4;j++){
123                 Button bt=new Button(a[i][j]);
124                 if(!a[i][j].equals("=")){
125                     int x=i,y=j;
126                     bt.setOnAction(actionEvent -> addToText(a[x][y]));
127                 }
128                 else {
129                     bt.setOnAction(actionEvent -> {
130                         try {
131                             cal();
132                         }
133                         catch (Exception e) {
134                             if(e instanceof MathException)
135                                 printError(e.toString());
136                             else
137                                 printError("Input Error!");
138                         }
139                     });
140                 }
141                 gridPane.add(bt,j,i+1);
142             }
143         }
144         return gridPane;
145     }
146     private VBox getVBox(){
147         VBox vBox=new VBox();
148         vBox.getStyleClass().add("vbox");
149 
150         textField=new HBox();
151         textField.getChildren().add(new Label("0.0"));
152         textField.setAlignment(Pos.CENTER_RIGHT);
153         textField.getStyleClass().add("text");
154         vBox.getChildren().add(textField);
155 
156         GridPane gridPane=getGridPane();
157         vBox.getChildren().add(gridPane);
158 
159         return vBox;
160     }
161     public void start(Stage stage){
162         Application.setUserAgentStylesheet("CalculatorGUI.css");
163         VBox vBox=getVBox();
164 
165         Scene scene=new Scene(vBox,300,350);
166         stage.setTitle("CalculatorGUI");
167         stage.setScene(scene);
168         stage.setMinWidth(300);
169         stage.setMinHeight(330);
170         stage.setHeight(330);
171         stage.show();
172     }
173     public static void main(String[] args){
174         Application.launch(args);
175     }
176 }
View Code

CSS部分:

 1 .button{
 2     -fx-alignment: center;
 3     -fx-background-color: #009FCC;
 4     -fx-background-radius: 0;
 5     -fx-text-fill: white;
 6     -fx-border-width: 0 2 2 0;
 7     -fx-border-color: black;
 8     -fx-border-style:solid;
 9     -fx-pref-height:40;
10     -fx-pref-width:50;
11 }
12 .button:hover{
13     -fx-background-color: #77DDFF;
14 }
15 .button:pressed{
16     -fx-background-color: #77DDFF;
17     -fx-border-color: #CCDDFF;
18     -fx-border-width: 2;
19 }
20 .gridPane{
21     -fx-background-color: #CCEEFF;
22     -fx-padding:10 0 20 25;
23 }
24 .text{
25     -fx-background-color: #CCEEFF;
26     -fx-background-radius:5 5 0 0;
27     -fx-pref-height: 50;
28     -fx-border-width: 2 0 0 2;
29     -fx-border-color: black;
30     -fx-border-radius:5 5 0 0;
31     -fx-border-style:solid;
32     -fx-padding:2;
33 }
34 .vbox{
35     -fx-padding: 20 10 10 10;
36     -fx-background-color:#009FCC;
37 }
View Code

--------END--------