一个小项目:JavaFx实现50道加减法

前言

太长时间没写博客了,其实这期间学了很多东西,但都是在记笔记没发过博客,这次借着学校的作业学了个新东西javaFx,比swing界面好看很多也方便很多,所以根据这个小项目准备写一篇博客,记录一下初学的javaFx,因为只学了四天,掌握的只是皮毛,所以如果有什么不妥的地方欢迎指正!

项目介绍

要求:java编写小程序,完成随机生成50道一百以内的不重复的加减法,可能需要输出混合运算。

思路:首先要编写习题类,用于生成简单的两个数运算习题;再编写混合运算类继承习题类,用于生成混合的加减法运算习题;由于需要图形界面输出,所以两个类都需要编写打印方法用于打印出习题。
         之后需要编写一个总的类,相当于习题本,包含一个习题数组的属性,这个习题数组既包含简单运算也包含混合运算(混合运算继承于简单运算),在这个类的构造函数中完成对习题的初始化,初始化的过程中检查重复性,由于生成是随机的,所以有几率习题会出现重复的情况,可以在出现重复的时候,在当前位置上重新生成习题。
         在编写GUI的时候选择了javaFx,因为就算是缺省的基本工具样式也很好看,用起来也方便。主要分有四个Pane,一个是根节点Pane,做下面三个Pane的父节点;两个页面Pane,第一页和第二页;一个最右边的输出成绩和页面showPane。
在功能方面需要完成:

  • 分页打印习题,可以上下翻页;
  • 输入框内只能输入数字,输入字符提示错误;
  • 摁下提交按钮后打印成绩和错题集,方便订正;
  • 可以多次提交成绩分别打印错题
  • 加入倒计时功能,督促学生在一定时间内完成习题。

代码

Exercise类:

public class Exercise {
    private int left;
    private int right;
    private char operate;
    private int result;
    private Random random = new Random();

    public Exercise(){
        left = random.nextInt(101);
        right = random.nextInt(101);
        if(random.nextInt(2) == 0){
            operate = '+';
            result = left + right;

        }else {
            operate = '-';
            result = left - right;
        }
    }
    public String print(){
        return (left+" "+operate+" "+right+ " = ");
    }

    public int getLeft() {
        return left;
    }

    public int getRight() {
        return right;
    }

    public char getOperate() {
        return operate;
    }

    public String getResult() {
        String res = Integer.toString(result);
        return res;
    }
}

mixExercise类:

public class mixExercise extends Exercise {//随机数个混合运算,混合运算包含的数字在(3,5)之间
    private Random random = new Random();
    private int size;
    private ArrayList<Integer> numList;
    private ArrayList<Character> opList;
    private int result;

    public mixExercise(){
        size = random.nextInt(3) + 3;
        numList = new ArrayList<>(size);
        opList = new ArrayList<>(size - 1);

        for(int i = 0; i < size - 1; i++){
            numList.add(random.nextInt(101));
            if(random.nextInt(2) == 0)opList.add('+');
            else opList.add('-');
        }
        numList.add(random.nextInt(101));

        result = numList.get(0);
        for(int i = 0; i < opList.size(); i++){
            if(opList.get(i) == '+'){
                result += numList.get(i + 1);
            }else {
                result -= numList.get(i + 1);
            }
        }
    }

    public String print(){
        String display = "";

        for(int i = 0; i < opList.size(); i++){
            display += numList.get(i);
            display += " " + opList.get(i) + " ";
        }
        display += numList.get(size - 1);
        return display + " = ";
    }

    @Override
    public String getResult() {
        String res = Integer.toString(result);
        return res;
    }

}

Operation类:

public class Operation {
    public ArrayList<Exercise> exercises;

    public Operation(int num_MixExercise){
        exercises = new ArrayList<>(50);
        for(int i = 0; i <= 50 - num_MixExercise;){
            Exercise exercise = new Exercise();
            if(!checkTheRepeat(exercise)){
                exercises.add(exercise);
                i++;
            }
        }
        for(int i = 0; i < num_MixExercise; i++){
            Exercise mixExercise = new mixExercise();
            exercises.add(mixExercise);
        }
    }

    public boolean checkTheRepeat(Exercise exercise){
        for(Exercise e : exercises){
            if(e.getLeft() == exercise.getLeft() && e.getRight() == exercise.getRight() && e.getResult() == exercise.getResult()){
                return true;
            }
        }
        return false;
    }
}

GUI编程部分:

public class Frame extends Application{
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage){
        AnchorPane root = new AnchorPane();
        //第一页
        AnchorPane page_1 = new AnchorPane();
        page_1.setStyle("-fx-background-image: url(./background.jpg)");
        page_1.setLayoutX(0);
        page_1.setLayoutY(0);
        page_1.setPrefWidth(1200);
        page_1.setPrefHeight(1000);
        //第二页
        AnchorPane page_2 = new AnchorPane();
        page_2.setStyle("-fx-background-image: url(./background.jpg)");
        page_2.setLayoutX(0);
        page_2.setLayoutY(0);
        page_2.setPrefWidth(1200);
        page_2.setPrefHeight(1000);
        //右侧展示页
        AnchorPane right = new AnchorPane();
        right.setStyle("-fx-background-image: url(./rightBack.jpg)");
        right.setPrefWidth(600);
        right.setPrefHeight(1000);
        right.setLayoutX(1200);
        right.setLayoutY(0);

        Button submit = new Button("提交");
        submit.setPrefWidth(110);
        submit.setPrefHeight(50);
        submit.setFont(Font.font("Inconsolata",20));
        submit.setCursor(Cursor.OPEN_HAND);
        submit.setStyle("-fx-background-color:#929FD1;"+ "-fx-background-radius: 20;");
        submit.setLayoutX(230);
        submit.setLayoutY(120);

        root.getChildren().add(page_1);
        root.getChildren().add(right);
        right.getChildren().add(submit);

        //规定加减法混合运算的个数
        int num_MixExercise = 3;
        Operation operation = new Operation(num_MixExercise);
        ArrayList<Text> textList = new ArrayList<>();
        ArrayList<TextField> textFieldList = new ArrayList<>();

        //从exercise中一一获取文本,并创造输入框
        for(Exercise e : operation.exercises){
            Text text = new Text();
            text.setText(e.print());
            textList.add(text);

            TextField textField = new TextField();
            textFieldList.add(textField);
         }
         //第一页布局
        int num = 0;
        for(int i = 0; i < 9; i++) { //九行五列(第一页)
            for(int j = 0; j < 5; j++) {
                Text text = textList.get(num);
                TextField textField = textFieldList.get(num);
                //调用统一的方法
                HBox box = setStyle(text,textField,i,j);
                HBox number = setNum(i,j,++num);
                page_1.getChildren().add(box);
                page_1.getChildren().add(number);
            }
        }

        //第二页布局
        //一行剩余简单运算
        int i = 0;
        for(; i < 5 - num_MixExercise; i++){
            Text text = textList.get(45 + i);
            TextField textField = textFieldList.get(45 + i);
            //掉用统一的方法
            HBox box = setStyle(text,textField,1,i);
            HBox number = setNum(1,i,46+i);
            page_2.getChildren().add(box);
            page_2.getChildren().add(number);
        }
        //num_MixExercise行规定的混合运算,此时调用不了setStyle了,因为各个参数都需要另调
        for(int j = 46 + i; j < 51; j++){
            Text text = textList.get(j);
            text.setX(50 + 220 );
            text.setY(50 + 100*(j - 46));
            text.setStyle("-fx-font-size: 20px;"+"-fx-font-family: STXihei;"+"-fx-font-weight: bolder");
            TextField textField = textFieldList.get(j);
            textField.setMaxWidth(70);
            textField.setLayoutX(150 + 350);
            textField.setLayoutY(29 + 100* (j - 46));
            textField.setStyle("-fx-background-color: #FDF9ED");

            HBox box = new HBox();
            box.setStyle("-fx-background-color: #E7C7D7;"+"-fx-border-color: #F17173;"+"-fx-border-style: dashed;" + "-fx-border-width: 5px;");
            box.getChildren().addAll(text,textField);
            box.setLayoutX(50);
            box.setLayoutY(50 + 100*(j - 46));
            box.setPrefWidth(350);
            box.setPrefHeight(40);
            box.setPadding(new Insets(12));
            page_2.getChildren().add(box);

            int m = j;
            Text n = new Text(String.valueOf(m));
            n.setFont(Font.font("Adobe 黑体 Std R"));
            HBox number = new HBox();
            number.setStyle("-fx-background-color: #F5EEF8;" + "-fx-border-style: dashed;" + "-fx-border-width: 3px;" + "-fx-border-color: #D2B4DE; ");
            number.getChildren().add(n);
            number.setLayoutX(48);
            number.setLayoutY(20 + 100*(j-46));
            number.setPrefWidth(40);
            number.setPrefHeight(12);
            number.setPadding(new Insets(5));
            page_2.getChildren().add(number);
        }

        Button slip = new Button("下一页");
        slip.setPrefWidth(80);
        slip.setPrefHeight(30);
        slip.setFont(Font.font("Inconsolata",16));
        slip.setCursor(Cursor.OPEN_HAND);
        slip.setStyle("-fx-background-color:#929FD1;"+ "-fx-background-radius: 15;");
        slip.setLayoutX(1100);
        slip.setLayoutY(10);
        page_1.getChildren().add(slip);

        //点击下一页
        slip.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                root.getChildren().add(page_2);
            }
        });

        Button pils = new Button("上一页");
        pils.setPrefWidth(80);
        pils.setPrefHeight(30);
        pils.setFont(Font.font("Inconsolata",16));
        pils.setCursor(Cursor.OPEN_HAND);
        pils.setStyle("-fx-background-color:#929FD1;"+ "-fx-background-radius: 15;");
        pils.setLayoutX(1100);
        pils.setLayoutY(10);
        page_2.getChildren().add(pils);

        //点击上一页
        pils.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                root.getChildren().remove(page_2);
            }
        });

        //红色提示
        wrongAnswerTip(textFieldList);

        //对窗口本身的设置
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        scene.setCursor(Cursor.DEFAULT);

        primaryStage.setTitle("每日50题");
        primaryStage.getIcons().add(new Image("./image50.jpg"));
        primaryStage.setWidth(1800);
        primaryStage.setHeight(1000);

        //展示窗口
        primaryStage.show();

        //右侧展示成绩的方框
        VBox showBox = new VBox();//-fx-background-color: #A9DFBF;
        showBox.setStyle("-fx-background-image: url(./show.jpg);"+"-fx-border-color: #52BE80;"+"-fx-border-style: dashed;"+"-fx-border-width: 5px");
        showBox.setLayoutX(45);
        showBox.setLayoutY(218);
        showBox.setPrefWidth(500);
        showBox.setPrefHeight(700);
        right.getChildren().add(showBox);


        //提交按钮的事件:get所有输入框的内容,再与习题答案一一比较得出成绩,输出错题集
        boolean[] correct = new boolean[51];
        submit.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                int num = 0;
                for(int i = 0; i < textFieldList.size(); i++){
                    if(textFieldList.get(i).getText().equals(operation.exercises.get(num).getResult())){
                        correct[num++] = true;
                    }else {
                        correct[num++] = false;
                    }
                }
                Text sore = new Text();
                sore.setStyle("-fx-font-family: 'Adobe 黑体 Std R';"+"-fx-font-size: 25px;"+"-fx-font-weight: bolder");
                showBox.setPadding(new Insets(70));
                int res = 0;
                for(boolean x : correct){
                    if(x){
                        res += 2;
                    }
                }
                //打印成绩和错题编号
                sore.setText("               成绩:   " + res);
                showBox.getChildren().add(sore);

                Text detail = new Text();
                detail.setText("  错题:");
                detail.setStyle("-fx-font-family: 'Adobe 黑体 Std R';" + "-fx-font-size: 20;" + "-fx-font-weight: bolder;" + "-fx-text-fill: #F17173");
                TextArea wrong = new TextArea();
                wrong.setStyle("-fx-font-family: 'Adobe 黑体 Std R';" + "-fx-font-size: 18;" + "-fx-font-weight: bolder;" + "-fx-text-fill: #F17173");
                String wrongWork = "";
                for(int i = 0; i < correct.length - 1; i++){
                    if( !correct[i] ){
                        wrongWork += (i+1)+"   ";
                    }
                }
                wrong.setWrapText(true);
                wrong.setText(wrongWork);
                showBox.getChildren().add(detail);
                showBox.getChildren().add(wrong);
            }
        });

        //倒计时的功能
        HBox timeBox = new HBox();
        timeBox.setStyle("-fx-background-color: #FDF9ED");
        timeBox.setLayoutX(90);
        timeBox.setLayoutY(20);
        timeBox.setPrefWidth(400);
        timeBox.setPrefHeight(50);
        timeBox.setPadding(new Insets(25));

        Text time = new Text("            倒计时:   ");
        time.setStyle("-fx-font-family: 'Adobe 黑体 Std R';"+"-fx-font-size: 25px;"+"-fx-font-weight: bolder;"+"-fx-text-fill: #2C4975");

        Clock clock = new Clock();
        clock.setPrefWidth(200);
        clock.setPrefHeight(50);
        right.getChildren().add(timeBox);
        timeBox.getChildren().addAll(time,clock);

    }

    public void wrongAnswerTip(ArrayList<TextField> textFieldList){
        //输入字符后输入框提示(变红)
        for(TextField textField : textFieldList){
            textField.textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    String regex=".*[a-zA-Z]+.*";
                    Matcher m=Pattern.compile(regex).matcher(newValue);
                    if(m.matches()){
                        textField.setStyle("-fx-background-color: #F17173");
                    }else {
                        textField.setStyle("-fx-background-color: #FDF9ED");
                    }
                }
            });
        }
    }

    public HBox setStyle(Text text, TextField textField, int i, int j){
        text.setX(50 + 220 * j);
        text.setY(50 + 100 * i);
        text.setStyle("-fx-font-size: 20px;"+"-fx-font-family: STXihei;"+"-fx-font-weight: bolder");
        textField.setMaxWidth(50);
        textField.setLayoutX(150 + 220 * j);
        textField.setLayoutY(29 + 100 * i);
        textField.setStyle("-fx-background-color: #FDF9ED");

        HBox box = new HBox();
        box.setStyle("-fx-background-color: #E7C7D7;"+"-fx-border-color: #F17173;"+"-fx-border-style: dashed;" + "-fx-border-width: 5px;");
        box.getChildren().addAll(text,textField);
        box.setLayoutX(50 + 220*j);
        box.setLayoutY(50 + 100*i);
        box.setPrefWidth(190);
        box.setPrefHeight(40);
        box.setPadding(new Insets(12));

        return box;
    }

    public HBox setNum(int i,int j,int count){
        int num = count;
        Text n = new Text(String.valueOf(num));
        n.setFont(Font.font("Adobe 黑体 Std R"));
        HBox number = new HBox();
        number.setStyle("-fx-background-color: #F5EEF8;" + "-fx-border-style: dashed;" + "-fx-border-width: 3px;" + "-fx-border-color: #D2B4DE; ");
        number.getChildren().add(n);
        number.setLayoutX(48 + 220*j);
        number.setLayoutY(20 + 100*i);
        number.setPrefWidth(40);
        number.setPrefHeight(12);
        number.setPadding(new Insets(5));

        return number;
    }
}

注释什么的都在代码里标注了,可能方法还是不精练,之后javaFx再深入学习会回来再改写一下。

运行界面

一个小项目:JavaFx实现50道加减法_第1张图片
一个小项目:JavaFx实现50道加减法_第2张图片
一个小项目:JavaFx实现50道加减法_第3张图片

你可能感兴趣的:(Java)