FishC 发表于 2023-12-29 22:58:00

zqy173590939 发表于 2023-12-29 22:57
@FishC

package com.example.javafxmw;

import...

这个问题出现在你的代码中找不到MySQL数据库驱动。要解决这个问题,你可以按照以下步骤操作:

1. 首先,确保你已经添加了MySQL的Java驱动依赖。

2. 在你的项目中添加MySQL的Java驱动依赖。你可以从MySQL官方网站上下载最新版本的驱动程序,或者使用Maven等构建工具来管理依赖。

3. 将下载的驱动程序(.jar文件)添加到你的项目中。你可以将它放置在项目的lib目录下,或者将其添加为IDE的库。

4. 确保你已经正确加载了MySQL的Java驱动。在你的代码中,你需要调用`Class.forName(JDBC_DRIVER)`来加载驱动程序。但是根据你的错误信息,可能是路径有问题。你可以尝试使用全限定类名来加载驱动程序:`Class.forName("com.mysql.cj.jdbc.Driver")`。

5. 如果你仍然遇到问题,请检查你的驱动程序是否正确配置和引入,以及数据库连接的URL、用户名和密码是否正确。

希望这些步骤能够帮助你解决问题!如果还有其他问题,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zqy173590939 发表于 2023-12-29 23:01:44

@FishC

package com.example.javafxmw;

import javafx.scene.control.*;
import shiyan4.EquationChecker;
import shiyan4.EquationCheckerOfRange;
import shiyan4.EquationCollection;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
import shiyan4.IEqualtion;

import java.io.IOException;
import java.sql.*;
import java.util.Optional;
import java.util.Scanner;

public class HelloApplication extends Application { // 声明HelloApplication类,继承自Application类
    private FlowPane flowPane; // 用于显示算术表达式和输入字段的FlowPane
    private TextField[] resultFields; // 用于存储结果输入字段的数组
    private int TopicNumber;
    // MySQL 5.x版本
    static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    // 注意数据库的名字要根据实际情况来,这里数据库名字是app
    static final String DB_URL = "jdbc:mysql://localhost:3306/shiyan8";

    static final String URL_EXTRA_PARA = "?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";

    // 数据库的用户名与密码,需要根据自己的设置
    static final String USER = "root";
    static final String PASS = "";


    @Override
    public void start(Stage stage) throws IOException { // 覆盖重写Application类的start方法,并声明可能抛出IOException异常

      MenuItem generateMenuItem = new MenuItem("产生习题"); // 创建一个名为"Generate"的菜单项
      MenuItem saveMenuItem = new MenuItem("保存习题"); // 创建一个名为"Generate"的菜单项
      MenuItem readMenuItem = new MenuItem("读取习题"); // 创建一个名为"Generate"的菜单项
      MenuItem checkMenuItem = new MenuItem("检查习题"); // 创建一个名为"Generate"的菜单项


      Menu fileMenu = new Menu("菜单"); // 创建一个名为"File"的菜单
      fileMenu.getItems().addAll(generateMenuItem); // 将generateMenuItem菜单项添加到fileMenu菜单中
      fileMenu.getItems().addAll(saveMenuItem);
      fileMenu.getItems().addAll(readMenuItem);
      fileMenu.getItems().addAll(checkMenuItem);

      MenuBar menuBar = new MenuBar(); // 创建一个菜单栏
      menuBar.getMenus().addAll(fileMenu); // 将fileMenu菜单添加到菜单栏中

      FlowPane flowPane = new FlowPane(); // 创建一个FlowPane布局
      flowPane.setHgap(20); // 设置水平间距为50
      flowPane.setVgap(30); // 设置垂直间距为30
      flowPane.setPadding(new Insets(30)); // 设置内边距为20

      BorderPane borderPane = new BorderPane(); // 创建一个BorderPane布局
      borderPane.setTop(menuBar); // 将菜单栏放置在顶部
      borderPane.setCenter(flowPane); // 将FlowPane布局放置在中间

      Scene scene = new Scene(borderPane, 800, 640); // 创建一个场景,将borderPane布局放置在其中,设置宽度为800,高度为640
      stage.setTitle("口算习题薄"); // 设置舞台的标题为"口算习题薄"
      stage.setScene(scene); // 将场景设置到舞台上
      stage.show(); // 显示舞台


      EquationChecker checker = new EquationCheckerOfRange(0, 100); // 创建一个范围检查器对象,用于检查生成的方程是否在指定范围内
      EquationCollection equa = new EquationCollection(); // 创建一个方程集合对象,用于存储生成的方程

      //产生习题
      generateMenuItem.setOnAction(actionEvent -> {
            //题目数量
            TextInputDialog textInputDialog = new TextInputDialog("");
            textInputDialog.setTitle("输入生成题目数量");
            textInputDialog.setHeaderText(null);
            textInputDialog.setContentText("数量:");
            Optional<String> textResult = textInputDialog.showAndWait();
            textResult.ifPresent(result -> {
                TopicNumber = Integer.parseInt(result);
            });

            equa.generate(TopicNumber, checker); // 调用方程集合对象的generate方法,生成指定数量的方程,并使用范围检查器进行检查
            flowPane.getChildren().clear(); // 清空FlowPane
            resultFields = new TextField; // 初始化resultFields数组以存储5个输入字段

            int i = 0;
            for (IEqualtion equation : equa) {
                String arithmeticExpression = i + 1 + "、" + equation.getNum1() + "" + equation.getOperator() + "" + equation.getNum2() + "="; // 生成一个随机算术表达式
                Label expressionLabel = new Label(arithmeticExpression); // 创建一个标签来显示算术表达式
                resultFields = new TextField(); // 创建一个文本字段用于输入结果
                resultFields.setPrefColumnCount(3); // 设置文本字段的列数为5,以容纳5个字符
                flowPane.getChildren().addAll(expressionLabel, resultFields); // 将标签和文本字段添加到FlowPane
                i++;
            }
      });


      //检查习题
      checkMenuItem.setOnAction(actionEvent -> {
            int i = 0;
            int score = 0;
            int[] fault = new int;
            for (IEqualtion equation : equa) {
                if (!resultFields.getText().isEmpty()) {
                  int result = Integer.parseInt(resultFields.getText()); // 从输入字段解析结果
                  if (equation.calculate() == result) {
                        score++;
                  } else {
                        fault = i + 1;
                  }
                } else {
                  fault = i + 1;
                }

                i++;
            }
            Alert alert = new Alert(Alert.AlertType.INFORMATION); // 创建一个信息警报
            StringBuilder FaultAssemble = new StringBuilder();
            for (int j = 0; j < TopicNumber; j++) {
                if (fault != 0) {
                  FaultAssemble.append(fault + ", ");
                }
            }
            alert.setContentText("你的成绩是: " + score + "\n" + "你的错题是: " + FaultAssemble.toString()); // 设置警报的内容

            alert.show(); // 显示警报
      });

      //保存习题
      saveMenuItem.setOnAction(actionEvent -> {
            Connection conn = null;
            Statement stmt = null;


            try {
                System.out.println("加载类从而注册驱动");
                Class.forName(JDBC_DRIVER);

                System.out.println("连接数据库...");
                conn = DriverManager.getConnection(DB_URL + URL_EXTRA_PARA, USER, PASS);

                DatabaseMetaData dbMeta = conn.getMetaData();
                System.out.println("当前用户:" + dbMeta.getUserName());
                System.out.println("驱动版本:" + dbMeta.getDriverVersion());
                System.out.println("MySQL版本:" + dbMeta.getDatabaseProductVersion());

                stmt = conn.createStatement();

                int i = 1;
                for (IEqualtion equaltion : equa) {
                  String exer = equaltion.getNum1() + " " + equaltion.getOperator() + " " + equaltion.getNum2() + " =";
                  String sql = "INSERT INTO topic (serial, exercise, answer) VALUES(" + i + ",' "+ exer +" '," + equaltion.calculate() + ")";
                  stmt.executeUpdate(sql);
                  i++;
                }


            } catch (SQLException se) {
                se.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                  if (stmt != null) stmt.close();
                  if (conn != null) conn.close();
                } catch (SQLException se) {
                  se.printStackTrace();
                }
            }

      });

    }

    public static void main(String[] args) { // 主方法
      launch(); // 启动JavaFX应用程序
    }


}

以上是实验代码,出现了以下问题,给出解决方案

java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver
      at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
      at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
      at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
      at java.base/java.lang.Class.forName0(Native Method)
      at java.base/java.lang.Class.forName(Class.java:421)
      at java.base/java.lang.Class.forName(Class.java:412)
      at com.example.javafxmw/com.example.javafxmw.HelloApplication.lambda$start$3(HelloApplication.java:139)
      at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
      at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
      at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
      at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
      at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
      at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
      at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
      at javafx.controls/javafx.scene.control.MenuItem.fire(MenuItem.java:459)
      at javafx.controls/com.sun.javafx.scene.control.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1385)
      at javafx.controls/com.sun.javafx.scene.control.ContextMenuContent$MenuItemContainer.lambda$createChildren$12(ContextMenuContent.java:1338)
      at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
      at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
      at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
      at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
      at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
      at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
      at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
      at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
      at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
      at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
      at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
      at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
      at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3897)
      at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1878)
      at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2623)
      at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
      at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
      at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
      at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
      at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
      at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
      at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:557)
      at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:943)
      at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
      at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
      at java.base/java.lang.Thread.run(Thread.java:1583)

FishC 发表于 2023-12-29 23:01:55

zqy173590939 发表于 2023-12-29 23:01
@FishC

package com.example.javafxmw;

import...

这个错误是因为找不到 `com.mysql.cj.jdbc.Driver` 类。这个类是 MySQL Connector/J 驱动包中的一个类,用于与 MySQL 数据库进行连接。

解决方案如下:

1. 确保已将 MySQL Connector/J 驱动包添加到项目中。可以从 MySQL 官网下载该驱动包(https://dev.mysql.com/downloads/connector/j/),并将其放置在项目的合适位置。

2. 确保已正确引入驱动包。可以通过在 IDE 中的项目配置中,添加该驱动包作为依赖项来实现。具体操作方法可能因所使用的 IDE 而有所不同,可以查找 IDE 的相关文档以了解如何添加依赖。

3. 确保驱动类的名称正确。`com.mysql.cj.jdbc.Driver` 是 MySQL 8.x 版本的驱动类名称,如果您使用的是 MySQL 5.x 版本,则将驱动类的名称更改为 `com.mysql.jdbc.Driver`。

执行以上步骤后,应该能够找到并加载正确的驱动类,从而解决该异常。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zqy173590939 发表于 2023-12-30 15:03:55

@FishC
package com.example.javafxmw;

import gaijin3.*;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.IOException;
import java.sql.*;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HelloApplication extends Application
{
    // 定义变量

    Button viewAccuracyButton = new Button("View Accuracy");


    FlowPane flowPane = new FlowPane();
    private int maxID = 0;

    @Override
    public void start(Stage stage) throws IOException {
      MenuItem generateMenuItem = new MenuItem("Generate");

      // 事件处理器代码
      generateMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 创建一个警示对话框
                TextInputDialog dialog = new TextInputDialog("5");
                dialog.setTitle("请输入算式数量");
                dialog.setHeaderText(null);
                dialog.setContentText("算式数量:");

                // 显示对话框,并获取用户输入的算式数量
                Optional<String> result = dialog.showAndWait();
                if (result.isPresent())
                {
                  int n = Integer.parseInt(result.get());

                  // 生成算式
                  EquationCollection equationCollection = generateEquations(n);

                  // 清空之前的内容
                  flowPane.getChildren().clear();

                  // 遍历算式集合并显示在GUI中
                  for (IEquation equation : equationCollection)
                  {
                        maxID++; // id自增
                        Label idLabel = new Label(String.valueOf(maxID)); // 获取当前最大ID,并将新的算式ID设为其加1
                        Label equationLabel = new Label(equation.toString());
                        TextField answerField = new TextField(); // 创建一个新的文本框
                        HBox equationBox = new HBox(10, idLabel, new Label("、"), equationLabel, answerField); // 将算式ID标签、顿号、算式标签和文本框放入水平布局
                        flowPane.getChildren().add(equationBox); // 将水平布局添加到 flowPane 中
                  }

                  // 连接数据库
                  connectDatabase();
                }
            }
      });

      MenuItem saveMenuItem = new MenuItem("Save");

      saveMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                saveEquations();
            }
      });

      MenuItem readMenuItem = new MenuItem("Read");

      readMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                flowPane.getChildren().clear(); // 清空当前GUI界面
                showAlert("习题已读取");
                displayAllEquationsFromDatabase();
            }
      });

      MenuItem checkMenuItem = new MenuItem("Check");

      checkMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 检查习题
                checkEquations();
            }
      });

      MenuItem viewAccuracyMenuItem = new MenuItem("View Accuracy");

      // View Accuracy按钮的点击事件监听器
      viewAccuracyButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 显示饼状图
                showAccuracyChart();
            }
      });



      Menu fileMenu = new Menu("File");
      Menu saveMenu = new Menu("SaveEquation");
      Menu readMenu = new Menu("ReadEquation");
      Menu checkMenu = new Menu("CheckEquation");

      fileMenu.getItems().addAll(generateMenuItem);
      saveMenu.getItems().add(saveMenuItem);
      readMenu.getItems().add(readMenuItem);
      checkMenu.getItems().add(checkMenuItem);

      MenuBar menuBar = new MenuBar();
      menuBar.getMenus().addAll(fileMenu);
      menuBar.getMenus().add(saveMenu);
      menuBar.getMenus().add(readMenu);
      menuBar.getMenus().add(checkMenu);

      flowPane.setHgap(50);
      flowPane.setVgap(30);
      flowPane.setPadding(new Insets(20));
      flowPane.setPrefSize(800, 560); // 设置 FlowPane 的大小

      BorderPane borderPane = new BorderPane();
      borderPane.setTop(menuBar);
      borderPane.setCenter(flowPane);
      HBox bottomBox = new HBox(10, viewAccuracyButton);
      borderPane.setBottom(bottomBox);

      Scene scene = new Scene(borderPane, 800, 640);
      stage.setTitle("口算习题薄");
      stage.setScene(scene);
      stage.show();
    }


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

    // 生成算式的方法
    public EquationCollection generateEquations(int n) {
      EquationCollection equationCollection = new EquationCollection();
      EquationCheckerOfRange equationChecker = new EquationCheckerOfRange(0, 100);
      equationCollection.generate(n, equationChecker);
      return equationCollection;
    }

    // 连接数据库的方法
    public void connectDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            DatabaseMetaData dbMeta = conn.getMetaData();
            System.out.println("当前用户:" + dbMeta.getUserName());
            System.out.println("驱动版本:" + dbMeta.getDriverVersion());
            System.out.println("MySQL版本:" + dbMeta.getDatabaseProductVersion());

            stmt = conn.createStatement();

            // 查询最大ID值
            ResultSet rs = stmt.executeQuery("SELECT MAX(id) FROM equationtable");
            if (rs.next()) {
                maxID = rs.getInt(1);
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void saveEquations() {
      Connection conn = null;
      PreparedStatement pstmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            for (Node node : flowPane.getChildren()) {
                if (node instanceof HBox) {
                  HBox equationBox = (HBox) node;
                  Label idLabel = (Label) equationBox.getChildren().get(0); // 获取算式ID标签
                  Label equationLabel = (Label) equationBox.getChildren().get(2);
                  TextField answerField = (TextField) equationBox.getChildren().get(3);

                  String equation = equationLabel.getText();
                  String answerText = answerField.getText();

                  // 检查答案字段是否为空
                  int answer = 0;
                  if (!answerText.isEmpty()) {
                        answer = Integer.parseInt(answerText);
                  }

                  // 计算正确结果
                  int result = calculateResult(equation);

                  // 保存到数据库
                  String sql = "INSERT INTO equationtable (id, Operand1, Operator, Operand2, Result) VALUES (?, ?, ?, ?, ?)";
                  pstmt = conn.prepareStatement(sql);
                  pstmt.setInt(1, Integer.parseInt(idLabel.getText())); // 将算式ID插入到数据库中
                  pstmt.setInt(2, getOperand1(equation));
                  pstmt.setString(3, getOperator(equation));
                  pstmt.setInt(4, getOperand2(equation));
                  pstmt.setInt(5, result);
                  pstmt.executeUpdate();
                }
            }

            System.out.println("算式保存成功!!!");
      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (pstmt != null)
                  pstmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }



    private int calculateResult(String equation) {
      String[] parts = equation.split(" ");
      int operand1 = Integer.parseInt(parts);
      int operand2 = Integer.parseInt(parts);
      String operator = parts;

      int result = 0;
      switch (operator) {
            case "+":
                result = operand1 + operand2;
                break;
            case "-":
                result = operand1 - operand2;
                break;
            case "*":          //此处预设乘法和除法便于以后相应的添加功能
                result = operand1 * operand2;
                break;
            case "/":
                result = operand1 / operand2;
                break;
      }

      return result;
    }

    private int getOperand1(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private String getOperator(String equation) {
      String[] parts = equation.split(" ");
      return parts;
    }

    private int getOperand2(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private void showAlert(String message) {
      Alert alert = new Alert(Alert.AlertType.INFORMATION);
      alert.setTitle("提示信息");
      alert.setHeaderText(null);
      alert.setContentText(message);
      alert.showAndWait();
    }

    private void displayAllEquationsFromDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            stmt = conn.createStatement();

            ResultSet rs = stmt.executeQuery("SELECT * FROM equationtable");
            if (!rs.next()) {
                showAlert("当前题库为空");
            } else {
                do {
                  int id = rs.getInt("id");
                  String equation = id + "、 " + rs.getInt("Operand1") + " " + rs.getString("Operator") + " " +
                            rs.getInt("Operand2") + " = " + rs.getInt("Result");
                  Label equationLabel = new Label(equation);
                  flowPane.getChildren().add(equationLabel);
                } while (rs.next());
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void checkEquations() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        equationBox.setStyle("-fx-background-color: #99ff99"); // 设置背景色为绿色
                        correctAnswers++;
                  } else { // 答案错误
                        equationBox.setStyle("-fx-background-color: #ff9999"); // 设置背景色为红色
                  }
                }
            }
      }
      showAlert("您一共答对了 " + correctAnswers + " 题,总共提交了 " + totalEquations + " 题。");
    }

    private void showAccuracyChart() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        correctAnswers++;
                  }
                }
            }
      }
      // 创建一个饼状图数据
      ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList(
                new PieChart.Data("Correct", correctAnswers),
                new PieChart.Data("Incorrect", totalEquations - correctAnswers)
      );
      // 创建饼状图
      PieChart chart = new PieChart(pieChartData);
      chart.setTitle("Accuracy Chart");
      // 创建一个新的Stage来显示饼状图
      Stage chartStage = new Stage();
      chartStage.setScene(new Scene(chart, 600, 400));
      chartStage.show();
    }

}
修改代码,保存算式后也调用showAlert方法,警示对话框内显示“保存成功!”
饼状图的正确和不正确的部分,增加所占的百分比显示,小数点后保留两位小数。

FishC 发表于 2023-12-30 15:05:00

zqy173590939 发表于 2023-12-30 15:03
@FishC
package com.example.javafxmw;

import ga ...

package com.example.javafxmw;

import gaijin3.*;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.IOException;
import java.sql.*;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HelloApplication extends Application
{
    // 定义变量

    Button viewAccuracyButton = new Button("View Accuracy");


    FlowPane flowPane = new FlowPane();
    private int maxID = 0;

    @Override
    public void start(Stage stage) throws IOException {
      MenuItem generateMenuItem = new MenuItem("Generate");

      // 事件处理器代码
      generateMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(ActionEvent event) {
                // 创建一个警示对话框
                TextInputDialog dialog = new TextInputDialog("5");
                dialog.setTitle("请输入算式数量");
                dialog.setHeaderText(null);
                dialog.setContentText("算式数量:");

                // 显示对话框,并获取用户输入的算式数量
                Optional result = dialog.showAndWait();
                if (result.isPresent())
                {
                  int n = Integer.parseInt(result.get());

                  // 生成算式
                  EquationCollection equationCollection = generateEquations(n);

                  // 清空之前的内容
                  flowPane.getChildren().clear();

                  // 遍历算式集合并显示在GUI中
                  for (IEquation equation : equationCollection)
                  {
                        maxID++; // id自增
                        Label idLabel = new Label(String.valueOf(maxID)); // 获取当前最大ID,并将新的算式ID设为其加1
                        Label equationLabel = new Label(equation.toString());
                        TextField answerField = new TextField(); // 创建一个新的文本框
                        HBox equationBox = new HBox(10, idLabel, new Label("、"), equationLabel, answerField); // 将算式ID标签、顿号、算式标签和文本框放入水平布局
                        flowPane.getChildren().add(equationBox); // 将水平布局添加到 flowPane 中
                  }

                  // 连接数据库
                  connectDatabase();
                }
            }
      });

      MenuItem saveMenuItem = new MenuItem("Save");

      saveMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(ActionEvent event) {
                saveEquations();
                showAlert("保存成功!");
            }
      });

      MenuItem readMenuItem = new MenuItem("Read");

      readMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(ActionEvent event) {
                flowPane.getChildren().clear(); // 清空当前GUI界面
                showAlert("习题已读取");
                displayAllEquationsFromDatabase();
            }
      });

      MenuItem checkMenuItem = new MenuItem("Check");

      checkMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(ActionEvent event) {
                // 检查习题
                checkEquations();
            }
      });

      MenuItem viewAccuracyMenuItem = new MenuItem("View Accuracy");

      // View Accuracy按钮的点击事件监听器
      viewAccuracyButton.setOnAction(new EventHandler() {
            @Override
            public void handle(ActionEvent event) {
                // 显示饼状图
                showAccuracyChart();
            }
      });



      Menu fileMenu = new Menu("File");
      Menu saveMenu = new Menu("SaveEquation");
      Menu readMenu = new Menu("ReadEquation");
      Menu checkMenu = new Menu("CheckEquation");

      fileMenu.getItems().addAll(generateMenuItem);
      saveMenu.getItems().add(saveMenuItem);
      readMenu.getItems().add(readMenuItem);
      checkMenu.getItems().add(checkMenuItem);

      MenuBar menuBar = new MenuBar();
      menuBar.getMenus().addAll(fileMenu);
      menuBar.getMenus().add(saveMenu);
      menuBar.getMenus().add(readMenu);
      menuBar.getMenus().add(checkMenu);

      flowPane.setHgap(50);
      flowPane.setVgap(30);
      flowPane.setPadding(new Insets(20));
      flowPane.setPrefSize(800, 560); // 设置 FlowPane 的大小

      BorderPane borderPane = new BorderPane();
      borderPane.setTop(menuBar);
      borderPane.setCenter(flowPane);
      HBox bottomBox = new HBox(10, viewAccuracyButton);
      borderPane.setBottom(bottomBox);

      Scene scene = new Scene(borderPane, 800, 640);
      stage.setTitle("口算习题薄");
      stage.setScene(scene);
      stage.show();
    }


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

    // 生成算式的方法
    public EquationCollection generateEquations(int n) {
      EquationCollection equationCollection = new EquationCollection();
      EquationCheckerOfRange equationChecker = new EquationCheckerOfRange(0, 100);
      equationCollection.generate(n, equationChecker);
      return equationCollection;
    }

    // 连接数据库的方法
    public void connectDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            DatabaseMetaData dbMeta = conn.getMetaData();
            System.out.println("当前用户:" + dbMeta.getUserName());
            System.out.println("驱动版本:" + dbMeta.getDriverVersion());
            System.out.println("MySQL版本:" + dbMeta.getDatabaseProductVersion());

            stmt = conn.createStatement();

            // 查询最大ID值
            ResultSet rs = stmt.executeQuery("SELECT MAX(id) FROM equationtable");
            if (rs.next()) {
                maxID = rs.getInt(1);
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void saveEquations() {
      Connection conn = null;
      PreparedStatement pstmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            for (Node node : flowPane.getChildren()) {
                if (node instanceof HBox) {
                  HBox equationBox = (HBox) node;
                  Label idLabel = (Label) equationBox.getChildren().get(0); // 获取算式ID标签
                  Label equationLabel = (Label) equationBox.getChildren().get(2);
                  TextField answerField = (TextField) equationBox.getChildren().get(3);

                  String equation = equationLabel.getText();
                  String answerText = answerField.getText();

                  // 检查答案字段是否为空
                  int answer = 0;
                  if (!answerText.isEmpty()) {
                        answer = Integer.parseInt(answerText);
                  }

                  // 计算正确结果
                  int result = calculateResult(equation);

                  // 保存到数据库
                  String sql = "INSERT INTO equationtable (id, Operand1, Operator, Operand2, Result) VALUES (?, ?, ?, ?, ?)";
                  pstmt = conn.prepareStatement(sql);
                  pstmt.setInt(1, Integer.parseInt(idLabel.getText())); // 将算式ID插入到数据库中
                  pstmt.setInt(2, getOperand1(equation));
                  pstmt.setString(3, getOperator(equation));
                  pstmt.setInt(4, getOperand2(equation));
                  pstmt.setInt(5, result);
                  pstmt.executeUpdate();
                }
            }

            System.out.println("算式保存成功!!!");
      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (pstmt != null)
                  pstmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }



    private int calculateResult(String equation) {
      String[] parts = equation.split(" ");
      int operand1 = Integer.parseInt(parts);
      int operand2 = Integer.parseInt(parts);
      String operator = parts;

      int result = 0;
      switch (operator) {
            case "+":
                result = operand1 + operand2;
                break;
            case "-":
                result = operand1 - operand2;
                break;
            case "*":          //此处预设乘法和除法便于以后相应的添加功能
                result = operand1 * operand2;
                break;
            case "/":
                result = operand1 / operand2;
                break;
      }

      return result;
    }

    private int getOperand1(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private String getOperator(String equation) {
      String[] parts = equation.split(" ");
      return parts;
    }

    private int getOperand2(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private void showAlert(String message) {
      Alert alert = new Alert(Alert.AlertType.INFORMATION);
      alert.setTitle("提示信息");
      alert.setHeaderText(null);
      alert.setContentText(message);
      alert.showAndWait();
    }

    private void displayAllEquationsFromDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            stmt = conn.createStatement();

            ResultSet rs = stmt.executeQuery("SELECT * FROM equationtable");
            if (!rs.next()) {
                showAlert("当前题库为空");
            } else {
                do {
                  int id = rs.getInt("id");
                  String equation = id + "、 " + rs.getInt("Operand1") + " " + rs.getString("Operator") + " " +
                            rs.getInt("Operand2") + " = " + rs.getInt("Result");
                  Label equationLabel = new Label(equation);
                  flowPane.getChildren().add(equationLabel);
                } while (rs.next());
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void checkEquations() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        equationBox.setStyle("-fx-background-color: #99ff99"); // 设置背景色为绿色
                        correctAnswers++;
                  } else { // 答案错误
                        equationBox.setStyle("-fx-background-color: #ff9999"); // 设置背景色为红色
                  }
                }
            }
      }
      showAlert("您一共答对了 " + correctAnswers + " 题,总共提交了 " + totalEquations + " 题。");
    }

    private void showAccuracyChart() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        correctAnswers++;
                  }
                }
            }
      }
      // 创建一个饼状图数据
      ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList(
                new PieChart.Data("Correct", correctAnswers),
                new PieChart.Data("Incorrect", totalEquations - correctAnswers)
      );
      
      // 计算百分比
      double correctPercent = (double) correctAnswers / totalEquations * 100;
      double incorrectPercent = 100 - correctPercent;
      
      // 设置饼状图数据的显示标签
      pieChartData.forEach(data -> {
            if (data.getName().equals("Correct")) {
                data.setName(data.getName() + " - " + String.format("%.2f", correctPercent) + "%");
            } else if (data.getName().equals("Incorrect")) {
                data.setName(data.getName() + " - " + String.format("%.2f", incorrectPercent) + "%");
            }
      });

      // 创建饼状图
      PieChart chart = new PieChart(pieChartData);
      chart.setTitle("Accuracy Chart");
      
      // 设置饼状图每个部分的标签可见
      chart.setLabelLineLength(10);
      chart.setLegendVisible(true);
      chart.setLabelsVisible(true);
      
      // 创建一个新的Stage来显示饼状图
      Stage chartStage = new Stage();
      chartStage.setScene(new Scene(chart, 600, 400));
      chartStage.show();
    }

}

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zqy173590939 发表于 2023-12-30 15:06:54

@FishC
package com.example.javafxmw;

import gaijin3.*;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.IOException;
import java.sql.*;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HelloApplication extends Application
{
    // 定义变量

    Button viewAccuracyButton = new Button("View Accuracy");


    FlowPane flowPane = new FlowPane();
    private int maxID = 0;

    @Override
    public void start(Stage stage) throws IOException {
      MenuItem generateMenuItem = new MenuItem("Generate");

      // 事件处理器代码
      generateMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 创建一个警示对话框
                TextInputDialog dialog = new TextInputDialog("5");
                dialog.setTitle("请输入算式数量");
                dialog.setHeaderText(null);
                dialog.setContentText("算式数量:");

                // 显示对话框,并获取用户输入的算式数量
                Optional<String> result = dialog.showAndWait();
                if (result.isPresent())
                {
                  int n = Integer.parseInt(result.get());

                  // 生成算式
                  EquationCollection equationCollection = generateEquations(n);

                  // 清空之前的内容
                  flowPane.getChildren().clear();

                  // 遍历算式集合并显示在GUI中
                  for (IEquation equation : equationCollection)
                  {
                        maxID++; // id自增
                        Label idLabel = new Label(String.valueOf(maxID)); // 获取当前最大ID,并将新的算式ID设为其加1
                        Label equationLabel = new Label(equation.toString());
                        TextField answerField = new TextField(); // 创建一个新的文本框
                        HBox equationBox = new HBox(10, idLabel, new Label("、"), equationLabel, answerField); // 将算式ID标签、顿号、算式标签和文本框放入水平布局
                        flowPane.getChildren().add(equationBox); // 将水平布局添加到 flowPane 中
                  }

                  // 连接数据库
                  connectDatabase();
                }
            }
      });

      MenuItem saveMenuItem = new MenuItem("Save");

      saveMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                saveEquations();
            }
      });

      MenuItem readMenuItem = new MenuItem("Read");

      readMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                flowPane.getChildren().clear(); // 清空当前GUI界面
                showAlert("习题已读取");
                displayAllEquationsFromDatabase();
            }
      });

      MenuItem checkMenuItem = new MenuItem("Check");

      checkMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 检查习题
                checkEquations();
            }
      });

      MenuItem viewAccuracyMenuItem = new MenuItem("View Accuracy");

      // View Accuracy按钮的点击事件监听器
      viewAccuracyButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 显示饼状图
                showAccuracyChart();
            }
      });



      Menu fileMenu = new Menu("File");
      Menu saveMenu = new Menu("SaveEquation");
      Menu readMenu = new Menu("ReadEquation");
      Menu checkMenu = new Menu("CheckEquation");

      fileMenu.getItems().addAll(generateMenuItem);
      saveMenu.getItems().add(saveMenuItem);
      readMenu.getItems().add(readMenuItem);
      checkMenu.getItems().add(checkMenuItem);

      MenuBar menuBar = new MenuBar();
      menuBar.getMenus().addAll(fileMenu);
      menuBar.getMenus().add(saveMenu);
      menuBar.getMenus().add(readMenu);
      menuBar.getMenus().add(checkMenu);

      flowPane.setHgap(50);
      flowPane.setVgap(30);
      flowPane.setPadding(new Insets(20));
      flowPane.setPrefSize(800, 560); // 设置 FlowPane 的大小

      BorderPane borderPane = new BorderPane();
      borderPane.setTop(menuBar);
      borderPane.setCenter(flowPane);
      HBox bottomBox = new HBox(10, viewAccuracyButton);
      borderPane.setBottom(bottomBox);

      Scene scene = new Scene(borderPane, 800, 640);
      stage.setTitle("口算习题薄");
      stage.setScene(scene);
      stage.show();
    }


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

    // 生成算式的方法
    public EquationCollection generateEquations(int n) {
      EquationCollection equationCollection = new EquationCollection();
      EquationCheckerOfRange equationChecker = new EquationCheckerOfRange(0, 100);
      equationCollection.generate(n, equationChecker);
      return equationCollection;
    }

    // 连接数据库的方法
    public void connectDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            DatabaseMetaData dbMeta = conn.getMetaData();
            System.out.println("当前用户:" + dbMeta.getUserName());
            System.out.println("驱动版本:" + dbMeta.getDriverVersion());
            System.out.println("MySQL版本:" + dbMeta.getDatabaseProductVersion());

            stmt = conn.createStatement();

            // 查询最大ID值
            ResultSet rs = stmt.executeQuery("SELECT MAX(id) FROM equationtable");
            if (rs.next()) {
                maxID = rs.getInt(1);
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void saveEquations() {
      Connection conn = null;
      PreparedStatement pstmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            for (Node node : flowPane.getChildren()) {
                if (node instanceof HBox) {
                  HBox equationBox = (HBox) node;
                  Label idLabel = (Label) equationBox.getChildren().get(0); // 获取算式ID标签
                  Label equationLabel = (Label) equationBox.getChildren().get(2);
                  TextField answerField = (TextField) equationBox.getChildren().get(3);

                  String equation = equationLabel.getText();
                  String answerText = answerField.getText();

                  // 检查答案字段是否为空
                  int answer = 0;
                  if (!answerText.isEmpty()) {
                        answer = Integer.parseInt(answerText);
                  }

                  // 计算正确结果
                  int result = calculateResult(equation);

                  // 保存到数据库
                  String sql = "INSERT INTO equationtable (id, Operand1, Operator, Operand2, Result) VALUES (?, ?, ?, ?, ?)";
                  pstmt = conn.prepareStatement(sql);
                  pstmt.setInt(1, Integer.parseInt(idLabel.getText())); // 将算式ID插入到数据库中
                  pstmt.setInt(2, getOperand1(equation));
                  pstmt.setString(3, getOperator(equation));
                  pstmt.setInt(4, getOperand2(equation));
                  pstmt.setInt(5, result);
                  pstmt.executeUpdate();
                }
            }

            System.out.println("算式保存成功!!!");
      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (pstmt != null)
                  pstmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }



    private int calculateResult(String equation) {
      String[] parts = equation.split(" ");
      int operand1 = Integer.parseInt(parts);
      int operand2 = Integer.parseInt(parts);
      String operator = parts;

      int result = 0;
      switch (operator) {
            case "+":
                result = operand1 + operand2;
                break;
            case "-":
                result = operand1 - operand2;
                break;
            case "*":          //此处预设乘法和除法便于以后相应的添加功能
                result = operand1 * operand2;
                break;
            case "/":
                result = operand1 / operand2;
                break;
      }

      return result;
    }

    private int getOperand1(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private String getOperator(String equation) {
      String[] parts = equation.split(" ");
      return parts;
    }

    private int getOperand2(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private void showAlert(String message) {
      Alert alert = new Alert(Alert.AlertType.INFORMATION);
      alert.setTitle("提示信息");
      alert.setHeaderText(null);
      alert.setContentText(message);
      alert.showAndWait();
    }

    private void displayAllEquationsFromDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            stmt = conn.createStatement();

            ResultSet rs = stmt.executeQuery("SELECT * FROM equationtable");
            if (!rs.next()) {
                showAlert("当前题库为空");
            } else {
                do {
                  int id = rs.getInt("id");
                  String equation = id + "、 " + rs.getInt("Operand1") + " " + rs.getString("Operator") + " " +
                            rs.getInt("Operand2") + " = " + rs.getInt("Result");
                  Label equationLabel = new Label(equation);
                  flowPane.getChildren().add(equationLabel);
                } while (rs.next());
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void checkEquations() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        equationBox.setStyle("-fx-background-color: #99ff99"); // 设置背景色为绿色
                        correctAnswers++;
                  } else { // 答案错误
                        equationBox.setStyle("-fx-background-color: #ff9999"); // 设置背景色为红色
                  }
                }
            }
      }
      showAlert("您一共答对了 " + correctAnswers + " 题,总共提交了 " + totalEquations + " 题。");
    }

    private void showAccuracyChart() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        correctAnswers++;
                  }
                }
            }
      }
      // 创建一个饼状图数据
      ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList(
                new PieChart.Data("Correct", correctAnswers),
                new PieChart.Data("Incorrect", totalEquations - correctAnswers)
      );
      // 创建饼状图
      PieChart chart = new PieChart(pieChartData);
      chart.setTitle("Accuracy Chart");
      // 创建一个新的Stage来显示饼状图
      Stage chartStage = new Stage();
      chartStage.setScene(new Scene(chart, 600, 400));
      chartStage.show();
    }

}
修改代码,保存算式后也调用showAlert方法,警示对话框内显示“保存成功!”
饼状图的正确和不正确的部分,增加所占的百分比显示,小数点后保留两位小数。
给出需要修改的部分即可

FishC 发表于 2023-12-30 15:07:42

zqy173590939 发表于 2023-12-30 15:06
@FishC
package com.example.javafxmw;

import ga ...

请修改以下两个地方:

1. 在saveEquations()方法中,将保存成功的提示信息传递给showAlert()方法:

System.out.println("算式保存成功!!!");
showAlert("保存成功!");

2. 在showAccuracyChart()方法中,计算正确和不正确的百分比,并添加到饼状图数据中:

double correctPercentage = (double) correctAnswers / totalEquations * 100;
double incorrectPercentage = 100 - correctPercentage;
ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList(
      new PieChart.Data("Correct (" + String.format("%.2f", correctPercentage) + "%)", correctAnswers),
      new PieChart.Data("Incorrect (" + String.format("%.2f", incorrectPercentage) + "%)", totalEquations - correctAnswers)
);

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zqy173590939 发表于 2023-12-30 15:28:21

package com.example.javafxmw;

import gaijin3.*;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

import java.io.IOException;
import java.sql.*;
import java.util.Optional;

public class HelloApplication extends Application
{
    // 定义变量

    Button viewAccuracyButton = new Button("View Accuracy");


    FlowPane flowPane = new FlowPane();
    private int maxID = 0;

    @Override
    public void start(Stage stage) throws IOException {
      MenuItem generateMenuItem = new MenuItem("Generate");

      // 事件处理器代码
      generateMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 创建一个警示对话框
                TextInputDialog dialog = new TextInputDialog("5");
                dialog.setTitle("请输入算式数量");
                dialog.setHeaderText(null);
                dialog.setContentText("算式数量:");

                // 显示对话框,并获取用户输入的算式数量
                Optional<String> result = dialog.showAndWait();
                if (result.isPresent())
                {
                  int n = Integer.parseInt(result.get());

                  // 生成算式
                  EquationCollection equationCollection = generateEquations(n);

                  // 清空之前的内容
                  flowPane.getChildren().clear();

                  // 遍历算式集合并显示在GUI中
                  for (IEquation equation : equationCollection)
                  {
                        maxID++; // id自增
                        Label idLabel = new Label(String.valueOf(maxID)); // 获取当前最大ID,并将新的算式ID设为其加1
                        Label equationLabel = new Label(equation.toString());
                        TextField answerField = new TextField(); // 创建一个新的文本框
                        HBox equationBox = new HBox(10, idLabel, new Label("、"), equationLabel, answerField); // 将算式ID标签、顿号、算式标签和文本框放入水平布局
                        flowPane.getChildren().add(equationBox); // 将水平布局添加到 flowPane 中
                  }

                  // 连接数据库
                  connectDatabase();
                }
            }
      });

      MenuItem saveMenuItem = new MenuItem("Save");

      saveMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                saveEquations();
            }
      });

      MenuItem readMenuItem = new MenuItem("Read");

      readMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                flowPane.getChildren().clear(); // 清空当前GUI界面
                showAlert("习题已读取");
                displayAllEquationsFromDatabase();
            }
      });

      MenuItem checkMenuItem = new MenuItem("Check");

      checkMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 检查习题
                checkEquations();
            }
      });

      MenuItem viewAccuracyMenuItem = new MenuItem("View Accuracy");

      // View Accuracy按钮的点击事件监听器
      viewAccuracyButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 显示饼状图
                showAccuracyChart();
            }
      });



      Menu fileMenu = new Menu("File");
      Menu saveMenu = new Menu("SaveEquation");
      Menu readMenu = new Menu("ReadEquation");
      Menu checkMenu = new Menu("CheckEquation");

      fileMenu.getItems().addAll(generateMenuItem);
      saveMenu.getItems().add(saveMenuItem);
      readMenu.getItems().add(readMenuItem);
      checkMenu.getItems().add(checkMenuItem);

      MenuBar menuBar = new MenuBar();
      menuBar.getMenus().addAll(fileMenu);
      menuBar.getMenus().add(saveMenu);
      menuBar.getMenus().add(readMenu);
      menuBar.getMenus().add(checkMenu);

      flowPane.setHgap(50);
      flowPane.setVgap(30);
      flowPane.setPadding(new Insets(20));
      flowPane.setPrefSize(800, 560); // 设置 FlowPane 的大小

      BorderPane borderPane = new BorderPane();
      borderPane.setTop(menuBar);
      borderPane.setCenter(flowPane);
      HBox bottomBox = new HBox(10, viewAccuracyButton);
      borderPane.setBottom(bottomBox);

      Scene scene = new Scene(borderPane, 800, 640);
      stage.setTitle("口算习题薄");
      stage.setScene(scene);
      stage.show();
    }


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

    // 生成算式的方法
    public EquationCollection generateEquations(int n) {
      EquationCollection equationCollection = new EquationCollection();
      EquationCheckerOfRange equationChecker = new EquationCheckerOfRange(0, 100);
      equationCollection.generate(n, equationChecker);
      return equationCollection;
    }

    // 连接数据库的方法
    public void connectDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            DatabaseMetaData dbMeta = conn.getMetaData();
            System.out.println("当前用户:" + dbMeta.getUserName());
            System.out.println("驱动版本:" + dbMeta.getDriverVersion());
            System.out.println("MySQL版本:" + dbMeta.getDatabaseProductVersion());

            stmt = conn.createStatement();

            // 查询最大ID值
            ResultSet rs = stmt.executeQuery("SELECT MAX(id) FROM equationtable");
            if (rs.next()) {
                maxID = rs.getInt(1);
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void saveEquations() {
      Connection conn = null;
      PreparedStatement pstmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            for (Node node : flowPane.getChildren()) {
                if (node instanceof HBox) {
                  HBox equationBox = (HBox) node;
                  Label idLabel = (Label) equationBox.getChildren().get(0); // 获取算式ID标签
                  Label equationLabel = (Label) equationBox.getChildren().get(2);
                  TextField answerField = (TextField) equationBox.getChildren().get(3);

                  String equation = equationLabel.getText();
                  String answerText = answerField.getText();

                  // 检查答案字段是否为空
                  int answer = 0;
                  if (!answerText.isEmpty()) {
                        answer = Integer.parseInt(answerText);
                  }

                  // 计算正确结果
                  int result = calculateResult(equation);

                  // 保存到数据库
                  String sql = "INSERT INTO equationtable (id, Operand1, Operator, Operand2, Result) VALUES (?, ?, ?, ?, ?)";
                  pstmt = conn.prepareStatement(sql);
                  pstmt.setInt(1, Integer.parseInt(idLabel.getText())); // 将算式ID插入到数据库中
                  pstmt.setInt(2, getOperand1(equation));
                  pstmt.setString(3, getOperator(equation));
                  pstmt.setInt(4, getOperand2(equation));
                  pstmt.setInt(5, result);
                  pstmt.executeUpdate();
                }
            }

            System.out.println("算式保存成功!!!");
            showAlert("保存成功!");
      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (pstmt != null)
                  pstmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }



    private int calculateResult(String equation) {
      String[] parts = equation.split(" ");
      int operand1 = Integer.parseInt(parts);
      int operand2 = Integer.parseInt(parts);
      String operator = parts;

      int result = 0;
      switch (operator) {
            case "+":
                result = operand1 + operand2;
                break;
            case "-":
                result = operand1 - operand2;
                break;
            case "*":          //此处预设乘法和除法便于以后相应的添加功能
                result = operand1 * operand2;
                break;
            case "/":
                result = operand1 / operand2;
                break;
      }

      return result;
    }

    private int getOperand1(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private String getOperator(String equation) {
      String[] parts = equation.split(" ");
      return parts;
    }

    private int getOperand2(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private void showAlert(String message) {
      Alert alert = new Alert(Alert.AlertType.INFORMATION);
      alert.setTitle("提示信息");
      alert.setHeaderText(null);
      alert.setContentText(message);
      alert.showAndWait();
    }

    private void displayAllEquationsFromDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            stmt = conn.createStatement();

            ResultSet rs = stmt.executeQuery("SELECT * FROM equationtable");
            if (!rs.next()) {
                showAlert("当前题库为空");
            } else {
                do {
                  int id = rs.getInt("id");
                  String equation = id + "、 " + rs.getInt("Operand1") + " " + rs.getString("Operator") + " " +
                            rs.getInt("Operand2") + " = " + rs.getInt("Result");
                  Label equationLabel = new Label(equation);
                  flowPane.getChildren().add(equationLabel);
                } while (rs.next());
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void checkEquations() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        equationBox.setStyle("-fx-background-color: #99ff99"); // 设置背景色为绿色
                        correctAnswers++;
                  } else { // 答案错误
                        equationBox.setStyle("-fx-background-color: #ff9999"); // 设置背景色为红色
                  }
                }
            }
      }
      showAlert("您一共答对了 " + correctAnswers + " 题,总共提交了 " + totalEquations + " 题。");
    }

    private void showAccuracyChart() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        correctAnswers++;
                  }
                }
            }
      }
      // 创建一个饼状图数据
      ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList(
                new PieChart.Data("Correct", correctAnswers),
                new PieChart.Data("Incorrect", totalEquations - correctAnswers)
      );
      
      // 创建饼状图
      PieChart chart = new PieChart(pieChartData);
      chart.setTitle("Accuracy Chart");
      // 创建一个新的Stage来显示饼状图
      Stage chartStage = new Stage();
      chartStage.setScene(new Scene(chart, 600, 400));
      chartStage.show();
      
    }

}
原本设想是,点击generate后,先从数据库中获取ID列的最大值并记录,如果数据库里没有ID则记为0,然后生成算数式的标号直接以这个被记录的最大值+1开始标号,但实际上,在第一次点击generate生成算式时,第一次生成的算数式没有获取到数据库中的ID列的最大值,还是从头开始生成的,第二次点击generate才正确获取到数据库的正确的最大ID号,生成的算数式展示在GUI中的才是正确的id。而且数据库中数据有变动后,比如点击了save,原本已存在10个算数式,保存了一个后,下次点击generate应该从第12个开始标号,但是实际上接下来第一次点击generate也是从11开始,从第二次点击generate开始才是正常的从12开始编号。
帮我检查一下以上代码的逻辑哪里与我的设想有出入导致了这种情况

FishC 发表于 2023-12-30 15:28:30

zqy173590939 发表于 2023-12-30 15:28
package com.example.javafxmw;

import gaijin3.*; ...

我注意到在saveEquations()方法中,您在保存算式之前获取了数据库中ID列的最大值,但是这个操作在第一次点击generate时并没有调用。这就导

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zqy173590939 发表于 2023-12-30 15:37:07

@FishC
package com.example.javafxmw;

import gaijin3.*;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

import java.io.IOException;
import java.sql.*;
import java.util.Optional;

public class HelloApplication extends Application
{
    // 定义变量

    Button viewAccuracyButton = new Button("View Accuracy");


    FlowPane flowPane = new FlowPane();
    private int maxID = 0;

    @Override
    public void start(Stage stage) throws IOException {
      MenuItem generateMenuItem = new MenuItem("Generate");

      // 事件处理器代码
      generateMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 创建一个警示对话框
                TextInputDialog dialog = new TextInputDialog("5");
                dialog.setTitle("请输入算式数量");
                dialog.setHeaderText(null);
                dialog.setContentText("算式数量:");

                // 显示对话框,并获取用户输入的算式数量
                Optional<String> result = dialog.showAndWait();
                if (result.isPresent())
                {
                  int n = Integer.parseInt(result.get());

                  // 生成算式
                  EquationCollection equationCollection = generateEquations(n);

                  // 清空之前的内容
                  flowPane.getChildren().clear();

                  // 遍历算式集合并显示在GUI中
                  for (IEquation equation : equationCollection)
                  {
                        maxID++; // id自增
                        Label idLabel = new Label(String.valueOf(maxID)); // 获取当前最大ID,并将新的算式ID设为其加1
                        Label equationLabel = new Label(equation.toString());
                        TextField answerField = new TextField(); // 创建一个新的文本框
                        HBox equationBox = new HBox(10, idLabel, new Label("、"), equationLabel, answerField); // 将算式ID标签、顿号、算式标签和文本框放入水平布局
                        flowPane.getChildren().add(equationBox); // 将水平布局添加到 flowPane 中
                  }

                  // 连接数据库
                  connectDatabase();
                }
            }
      });

      MenuItem saveMenuItem = new MenuItem("Save");

      saveMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                saveEquations();
            }
      });

      MenuItem readMenuItem = new MenuItem("Read");

      readMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                flowPane.getChildren().clear(); // 清空当前GUI界面
                showAlert("习题已读取");
                displayAllEquationsFromDatabase();
            }
      });

      MenuItem checkMenuItem = new MenuItem("Check");

      checkMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 检查习题
                checkEquations();
            }
      });

      MenuItem viewAccuracyMenuItem = new MenuItem("View Accuracy");

      // View Accuracy按钮的点击事件监听器
      viewAccuracyButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 显示饼状图
                showAccuracyChart();
            }
      });



      Menu fileMenu = new Menu("File");
      Menu saveMenu = new Menu("SaveEquation");
      Menu readMenu = new Menu("ReadEquation");
      Menu checkMenu = new Menu("CheckEquation");

      fileMenu.getItems().addAll(generateMenuItem);
      saveMenu.getItems().add(saveMenuItem);
      readMenu.getItems().add(readMenuItem);
      checkMenu.getItems().add(checkMenuItem);

      MenuBar menuBar = new MenuBar();
      menuBar.getMenus().addAll(fileMenu);
      menuBar.getMenus().add(saveMenu);
      menuBar.getMenus().add(readMenu);
      menuBar.getMenus().add(checkMenu);

      flowPane.setHgap(50);
      flowPane.setVgap(30);
      flowPane.setPadding(new Insets(20));
      flowPane.setPrefSize(800, 560); // 设置 FlowPane 的大小

      BorderPane borderPane = new BorderPane();
      borderPane.setTop(menuBar);
      borderPane.setCenter(flowPane);
      HBox bottomBox = new HBox(10, viewAccuracyButton);
      borderPane.setBottom(bottomBox);

      Scene scene = new Scene(borderPane, 800, 640);
      stage.setTitle("口算习题薄");
      stage.setScene(scene);
      stage.show();
    }


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

    // 生成算式的方法
    public EquationCollection generateEquations(int n) {
      EquationCollection equationCollection = new EquationCollection();
      EquationCheckerOfRange equationChecker = new EquationCheckerOfRange(0, 100);
      equationCollection.generate(n, equationChecker);
      return equationCollection;
    }

    // 连接数据库的方法
    public void connectDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            DatabaseMetaData dbMeta = conn.getMetaData();
            System.out.println("当前用户:" + dbMeta.getUserName());
            System.out.println("驱动版本:" + dbMeta.getDriverVersion());
            System.out.println("MySQL版本:" + dbMeta.getDatabaseProductVersion());

            stmt = conn.createStatement();

            // 查询最大ID值
            ResultSet rs = stmt.executeQuery("SELECT MAX(id) FROM equationtable");
            if (rs.next()) {
                maxID = rs.getInt(1);
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void saveEquations() {
      Connection conn = null;
      PreparedStatement pstmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            for (Node node : flowPane.getChildren()) {
                if (node instanceof HBox) {
                  HBox equationBox = (HBox) node;
                  Label idLabel = (Label) equationBox.getChildren().get(0); // 获取算式ID标签
                  Label equationLabel = (Label) equationBox.getChildren().get(2);
                  TextField answerField = (TextField) equationBox.getChildren().get(3);

                  String equation = equationLabel.getText();
                  String answerText = answerField.getText();

                  // 检查答案字段是否为空
                  int answer = 0;
                  if (!answerText.isEmpty()) {
                        answer = Integer.parseInt(answerText);
                  }

                  // 计算正确结果
                  int result = calculateResult(equation);

                  // 保存到数据库
                  String sql = "INSERT INTO equationtable (id, Operand1, Operator, Operand2, Result) VALUES (?, ?, ?, ?, ?)";
                  pstmt = conn.prepareStatement(sql);
                  pstmt.setInt(1, Integer.parseInt(idLabel.getText())); // 将算式ID插入到数据库中
                  pstmt.setInt(2, getOperand1(equation));
                  pstmt.setString(3, getOperator(equation));
                  pstmt.setInt(4, getOperand2(equation));
                  pstmt.setInt(5, result);
                  pstmt.executeUpdate();
                }
            }

            System.out.println("算式保存成功!!!");
            showAlert("保存成功!");
      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (pstmt != null)
                  pstmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }



    private int calculateResult(String equation) {
      String[] parts = equation.split(" ");
      int operand1 = Integer.parseInt(parts);
      int operand2 = Integer.parseInt(parts);
      String operator = parts;

      int result = 0;
      switch (operator) {
            case "+":
                result = operand1 + operand2;
                break;
            case "-":
                result = operand1 - operand2;
                break;
            case "*":          //此处预设乘法和除法便于以后相应的添加功能
                result = operand1 * operand2;
                break;
            case "/":
                result = operand1 / operand2;
                break;
      }

      return result;
    }

    private int getOperand1(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private String getOperator(String equation) {
      String[] parts = equation.split(" ");
      return parts;
    }

    private int getOperand2(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private void showAlert(String message) {
      Alert alert = new Alert(Alert.AlertType.INFORMATION);
      alert.setTitle("提示信息");
      alert.setHeaderText(null);
      alert.setContentText(message);
      alert.showAndWait();
    }

    private void displayAllEquationsFromDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            stmt = conn.createStatement();

            ResultSet rs = stmt.executeQuery("SELECT * FROM equationtable");
            if (!rs.next()) {
                showAlert("当前题库为空");
            } else {
                do {
                  int id = rs.getInt("id");
                  String equation = id + "、 " + rs.getInt("Operand1") + " " + rs.getString("Operator") + " " +
                            rs.getInt("Operand2") + " = " + rs.getInt("Result");
                  Label equationLabel = new Label(equation);
                  flowPane.getChildren().add(equationLabel);
                } while (rs.next());
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void checkEquations() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        equationBox.setStyle("-fx-background-color: #99ff99"); // 设置背景色为绿色
                        correctAnswers++;
                  } else { // 答案错误
                        equationBox.setStyle("-fx-background-color: #ff9999"); // 设置背景色为红色
                  }
                }
            }
      }
      showAlert("您一共答对了 " + correctAnswers + " 题,总共提交了 " + totalEquations + " 题。");
    }

    private void showAccuracyChart() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        correctAnswers++;
                  }
                }
            }
      }
      // 创建一个饼状图数据
      ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList(
                new PieChart.Data("Correct", correctAnswers),
                new PieChart.Data("Incorrect", totalEquations - correctAnswers)
      );
      
      // 创建饼状图
      PieChart chart = new PieChart(pieChartData);
      chart.setTitle("Accuracy Chart");
      // 创建一个新的Stage来显示饼状图
      Stage chartStage = new Stage();
      chartStage.setScene(new Scene(chart, 600, 400));
      chartStage.show();
      
    }

}
原本设想是,点击generate后,先从数据库中获取ID列的最大值并记录,如果数据库里没有ID则记为0,然后生成算数式的标号直接以这个被记录的最大值+1开始标号,但实际上,在第一次点击generate生成算式时,第一次生成的算数式没有获取到数据库中的ID列的最大值,还是从头开始生成的,第二次点击generate才正确获取到数据库的正确的最大ID号,生成的算数式展示在GUI中的才是正确的id。而且数据库中数据有变动后,比如点击了save,原本已存在10个算数式,保存了一个后,下次点击generate应该从第12个开始标号,但是实际上接下来第一次点击generate也是从11开始,从第二次点击generate开始才是正常的从12开始编号。
帮我检查一下以上代码的逻辑哪里与我的设想有出入导致了这种情况

FishC 发表于 2023-12-30 15:37:20

zqy173590939 发表于 2023-12-30 15:37
@FishC
package com.example.javafxmw;

import ga ...

你的代码逻辑中,获取数据库中最大ID值的部分放在了连接数据库的方法中。这会导致在每次点击生成算式之前都要重新连接数据库来获取最大ID值。而实际上,获取最大ID值应该在程序启动时只获取一次即可。

为了解决该问题,你可以将获取最大ID值的代码移到程序启动时调用的`start()`方法中。具体操作如下:

1. 在`HelloApplication`类中添加一个私有变量`maxID`,用于记录最大ID值。
private int maxID = 0;

2. 在`start()`方法中,将获取数据库中最大ID值的代码片段移动到连接数据库之后。
// 连接数据库
connectDatabase();

// 查询最大ID值
ResultSet rs = stmt.executeQuery("SELECT MAX(id) FROM equationtable");
if (rs.next()) {
    maxID = rs.getInt(1);
}

3. 修改生成算式的代码。将算式的ID标签直接使用`maxID`变量来设置。
for (IEquation equation : equationCollection) {
    maxID++; // id自增
    Label idLabel = new Label(String.valueOf(maxID)); // 使用maxID作为算式ID
    // 其他代码...
}

通过以上修改,生成算式时的ID标签就会按照预期的逻辑进行自增了。并且不会在每次生成算式之前都重新连接数据库获取最大ID值了。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zqy173590939 发表于 2023-12-31 14:03:40

@FishC
package com.example.javafxmw;

import gaijin3.*;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

import java.io.IOException;
import java.sql.*;
import java.util.Optional;

public class HelloApplication extends Application
{
    // 定义变量

    Button viewAccuracyButton = new Button("View Accuracy");


    FlowPane flowPane = new FlowPane();
    private int maxID = 0;

    @Override
    public void start(Stage stage) throws IOException {
      MenuItem generateMenuItem = new MenuItem("Generate");

      // 事件处理器代码
      generateMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 创建一个警示对话框
                TextInputDialog dialog = new TextInputDialog("5");
                dialog.setTitle("请输入算式数量");
                dialog.setHeaderText(null);
                dialog.setContentText("算式数量:");

                // 显示对话框,并获取用户输入的算式数量
                Optional<String> result = dialog.showAndWait();
                if (result.isPresent())
                {
                  int n = Integer.parseInt(result.get());

                  // 生成算式
                  EquationCollection equationCollection = generateEquations(n);

                  // 清空之前的内容
                  flowPane.getChildren().clear();

                  // 遍历算式集合并显示在GUI中
                  for (IEquation equation : equationCollection)
                  {
                        maxID++; // id自增
                        Label idLabel = new Label(String.valueOf(maxID)); // 获取当前最大ID,并将新的算式ID设为其加1
                        Label equationLabel = new Label(equation.toString());
                        TextField answerField = new TextField(); // 创建一个新的文本框
                        HBox equationBox = new HBox(10, idLabel, new Label("、"), equationLabel, answerField); // 将算式ID标签、顿号、算式标签和文本框放入水平布局
                        flowPane.getChildren().add(equationBox); // 将水平布局添加到 flowPane 中
                  }

                  // 连接数据库
                  connectDatabase();
                }
            }
      });

      MenuItem saveMenuItem = new MenuItem("Save");

      saveMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                saveEquations();
                connectDatabase();
            }
      });

      MenuItem readMenuItem = new MenuItem("Read");

      readMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                flowPane.getChildren().clear(); // 清空当前GUI界面
                showAlert("习题已读取");
                displayAllEquationsFromDatabase();
            }
      });

      MenuItem checkMenuItem = new MenuItem("Check");

      checkMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 检查习题
                checkEquations();
            }
      });


      // View Accuracy按钮的点击事件监听器
      viewAccuracyButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 显示饼状图
                showAccuracyChart();
            }
      });



      Menu fileMenu = new Menu("File");
      Menu saveMenu = new Menu("SaveEquation");
      Menu readMenu = new Menu("ReadEquation");
      Menu checkMenu = new Menu("CheckEquation");

      fileMenu.getItems().addAll(generateMenuItem);
      saveMenu.getItems().add(saveMenuItem);
      readMenu.getItems().add(readMenuItem);
      checkMenu.getItems().add(checkMenuItem);

      MenuBar menuBar = new MenuBar();
      menuBar.getMenus().addAll(fileMenu);
      menuBar.getMenus().add(saveMenu);
      menuBar.getMenus().add(readMenu);
      menuBar.getMenus().add(checkMenu);

      flowPane.setHgap(50);
      flowPane.setVgap(30);
      flowPane.setPadding(new Insets(20));
      flowPane.setPrefSize(800, 560); // 设置 FlowPane 的大小

      BorderPane borderPane = new BorderPane();
      borderPane.setTop(menuBar);
      borderPane.setCenter(flowPane);
      HBox bottomBox = new HBox(10, viewAccuracyButton);
      borderPane.setBottom(bottomBox);

      Scene scene = new Scene(borderPane, 800, 640);
      stage.setTitle("口算习题薄");
      stage.setScene(scene);
      stage.show();
    }


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

    // 生成算式的方法
    public EquationCollection generateEquations(int n) {
      EquationCollection equationCollection = new EquationCollection();
      EquationCheckerOfRange equationChecker = new EquationCheckerOfRange(0, 100);
      equationCollection.generate(n, equationChecker);
      return equationCollection;
    }

    // 连接数据库的方法
    public void connectDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            DatabaseMetaData dbMeta = conn.getMetaData();
            System.out.println("当前用户:" + dbMeta.getUserName());
            System.out.println("驱动版本:" + dbMeta.getDriverVersion());
            System.out.println("MySQL版本:" + dbMeta.getDatabaseProductVersion());

            stmt = conn.createStatement();

            // 查询最大ID值
            ResultSet rs = stmt.executeQuery("SELECT MAX(id) FROM equationtable");
            if (rs.next()) {
                maxID = rs.getInt(1);
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void saveEquations() {
      Connection conn = null;
      PreparedStatement pstmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            for (Node node : flowPane.getChildren()) {
                if (node instanceof HBox) {
                  HBox equationBox = (HBox) node;
                  Label idLabel = (Label) equationBox.getChildren().get(0); // 获取算式ID标签
                  Label equationLabel = (Label) equationBox.getChildren().get(2);
                  TextField answerField = (TextField) equationBox.getChildren().get(3);

                  String equation = equationLabel.getText();
                  String answerText = answerField.getText();

                  // 检查答案字段是否为空
                  int answer = 0;
                  if (!answerText.isEmpty()) {
                        answer = Integer.parseInt(answerText);
                  }

                  // 计算正确结果
                  int result = calculateResult(equation);

                  // 保存到数据库
                  String sql = "INSERT INTO equationtable (id, Operand1, Operator, Operand2, Result) VALUES (?, ?, ?, ?, ?)";
                  pstmt = conn.prepareStatement(sql);
                  pstmt.setInt(1, Integer.parseInt(idLabel.getText())); // 将算式ID插入到数据库中
                  pstmt.setInt(2, getOperand1(equation));
                  pstmt.setString(3, getOperator(equation));
                  pstmt.setInt(4, getOperand2(equation));
                  pstmt.setInt(5, result);
                  pstmt.executeUpdate();
                }
            }

            System.out.println("算式保存成功!!!");
            showAlert("保存成功!");
      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (pstmt != null)
                  pstmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }



    private int calculateResult(String equation) {
      String[] parts = equation.split(" ");
      int operand1 = Integer.parseInt(parts);
      int operand2 = Integer.parseInt(parts);
      String operator = parts;

      int result = 0;
      switch (operator) {
            case "+":
                result = operand1 + operand2;
                break;
            case "-":
                result = operand1 - operand2;
                break;
            case "*":          //此处预设乘法和除法便于以后相应的添加功能
                result = operand1 * operand2;
                break;
            case "/":
                result = operand1 / operand2;
                break;
      }

      return result;
    }

    private int getOperand1(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private String getOperator(String equation) {
      String[] parts = equation.split(" ");
      return parts;
    }

    private int getOperand2(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private void showAlert(String message) {
      Alert alert = new Alert(Alert.AlertType.INFORMATION);
      alert.setTitle("提示信息");
      alert.setHeaderText(null);
      alert.setContentText(message);
      alert.showAndWait();
    }

    private void displayAllEquationsFromDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            stmt = conn.createStatement();

            ResultSet rs = stmt.executeQuery("SELECT * FROM equationtable");
            if (!rs.next()) {
                showAlert("当前题库为空");
            } else {
                do {
                  int id = rs.getInt("id");
                  String equation = id + "、 " + rs.getInt("Operand1") + " " + rs.getString("Operator") + " " +
                            rs.getInt("Operand2") + " = " + rs.getInt("Result");
                  Label equationLabel = new Label(equation);
                  flowPane.getChildren().add(equationLabel);
                } while (rs.next());
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void checkEquations() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        equationBox.setStyle("-fx-background-color: #99ff99"); // 设置背景色为绿色
                        correctAnswers++;
                  } else { // 答案错误
                        equationBox.setStyle("-fx-background-color: #ff9999"); // 设置背景色为红色
                  }
                }
            }
      }
      showAlert("您一共答对了 " + correctAnswers + " 题,总共提交了 " + totalEquations + " 题。");
    }

    private void showAccuracyChart() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        correctAnswers++;
                  }
                }
            }
      }
      // 创建一个饼状图数据
      double correctPercentage = (double) correctAnswers / totalEquations * 100;
      double incorrectPercentage = 100 - correctPercentage;
      ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList(
                new PieChart.Data("Correct (" + String.format("%.2f", correctPercentage)
                        + "%)", correctAnswers),
                new PieChart.Data("Incorrect (" + String.format("%.2f", incorrectPercentage)
                        + "%)", totalEquations - correctAnswers)
      );

      // 创建饼状图
      PieChart chart = new PieChart(pieChartData);
      chart.setTitle("Accuracy Chart");
      // 创建一个新的Stage来显示饼状图
      Stage chartStage = new Stage();
      chartStage.setScene(new Scene(chart, 600, 400));
      chartStage.show();

    }

}
添加功能,在界面的右下角展示一个空白框,框内显示以下内容:
统计信息:(在最上方,意思是统计的以下内容进行展示)
总题数:(检查check执行后,已回答的题目计入总题数,未回答的题目不计入总数)
正确题数:
错误题数:(总题数,正确题数,错误题数放在一行里,中间适当间隔一定间距)
正确率:
错误率:(正确率和错误率放在一行里,中间适当间隔一定间距)

FishC 发表于 2023-12-31 14:06:02

zqy173590939 发表于 2023-12-31 14:03
@FishC
package com.example.javafxmw;

import ga ...

要在界面的右下角添加一个空白框,并展示统计信息,可以按照以下步骤进行操作:

1. 在界面的右下角创建一个Label组件,用于显示统计信息。例如:

Label statisticsLabel = new Label();

2. 在checkEquations()方法中,统计总题数、正确题数和错误题数,并计算正确率和错误率。修改showAlert()方法,将统计信息显示在statisticsLabel中。例如:

private void checkEquations() {
    int totalEquations = 0; // 总题数
    int correctAnswers = 0; // 答对题数
    int incorrectAnswers = 0; // 答错题数

    for (Node node : flowPane.getChildren()) {
      // ...
      // 统计总题数、正确题数和错误题数
    }

    double correctRate = (double) correctAnswers / totalEquations * 100;
    double incorrectRate = (double) incorrectAnswers / totalEquations * 100;

    String statistics = "统计信息:\n" +
            "总题数:" + totalEquations + "\n" +
            "正确题数:" + correctAnswers + "\n" +
            "错误题数:" + incorrectAnswers + "\n" +
            "正确率:" + String.format("%.2f", correctRate) + "%\n" +
            "错误率:" + String.format("%.2f", incorrectRate) + "%";

    showAlert("您一共答对了 " + correctAnswers + " 题,总共提交了 " + totalEquations + " 题。");
    statisticsLabel.setText(statistics);
}

3. 将statisticsLabel添加到界面的底部。

HBox bottomBox = new HBox(10, viewAccuracyButton); // 原来的底部HBox组件
borderPane.setBottom(bottomBox); // 将HBox组件添加到界面底部
borderPane.setRight(statisticsLabel); // 将statisticsLabel添加到界面右侧

这样就在界面的右下角展示了一个空白框,框内显示了统计信息。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zqy173590939 发表于 2023-12-31 14:08:35

FishC 发表于 2023-12-31 14:06
要在界面的右下角添加一个空白框,并展示统计信息,可以按照以下步骤进行操作:

1. 在界面的右下角 ...

修改代码,这个空白框要求离边框有20像素

FishC 发表于 2023-12-31 14:08:59

zqy173590939 发表于 2023-12-31 14:08
修改代码,这个空白框要求离边框有20像素

要将空白框与边框保持20像素的间距,可以使用Insets来设置BorderPane的填充。以下是修改后的代码示例:

// 修改flowPane的填充为20像素
flowPane.setPadding(new Insets(20));

// 创建空白框,并设置填充为20像素
Label statisticsLabel = new Label();
statisticsLabel.setPadding(new Insets(20));

// 将statisticsLabel添加到界面的底部右侧
HBox bottomBox = new HBox(10, viewAccuracyButton);
bottomBox.setPadding(new Insets(0, 20, 20, 0)); // 右下的边距为20像素
borderPane.setBottom(bottomBox);
borderPane.setRight(statisticsLabel);

通过设置填充,可以确保空白框与边框之间有20像素的间距,并且统计信息会在空白框内显示。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zqy173590939 发表于 2023-12-31 14:26:21

@FishC
package com.example.javafxmw;

import gaijin3.*;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

import java.io.IOException;
import java.sql.*;
import java.util.Optional;

public class HelloApplication extends Application
{
    // 定义变量

    Button viewAccuracyButton = new Button("View Accuracy");


    FlowPane flowPane = new FlowPane();
    private int maxID = 0;

    @Override
    public void start(Stage stage) throws IOException {
      MenuItem generateMenuItem = new MenuItem("Generate");

      // 事件处理器代码
      generateMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 创建一个警示对话框
                TextInputDialog dialog = new TextInputDialog("5");
                dialog.setTitle("请输入算式数量");
                dialog.setHeaderText(null);
                dialog.setContentText("算式数量:");

                // 显示对话框,并获取用户输入的算式数量
                Optional<String> result = dialog.showAndWait();
                if (result.isPresent())
                {
                  int n = Integer.parseInt(result.get());

                  // 生成算式
                  EquationCollection equationCollection = generateEquations(n);

                  // 清空之前的内容
                  flowPane.getChildren().clear();

                  // 遍历算式集合并显示在GUI中
                  for (IEquation equation : equationCollection)
                  {
                        maxID++; // id自增
                        Label idLabel = new Label(String.valueOf(maxID)); // 获取当前最大ID,并将新的算式ID设为其加1
                        Label equationLabel = new Label(equation.toString());
                        TextField answerField = new TextField(); // 创建一个新的文本框
                        HBox equationBox = new HBox(10, idLabel, new Label("、"), equationLabel, answerField); // 将算式ID标签、顿号、算式标签和文本框放入水平布局
                        flowPane.getChildren().add(equationBox); // 将水平布局添加到 flowPane 中
                  }

                  // 连接数据库
                  connectDatabase();
                }
            }
      });

      MenuItem saveMenuItem = new MenuItem("Save");

      saveMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                saveEquations();
                connectDatabase();
            }
      });

      MenuItem readMenuItem = new MenuItem("Read");

      readMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                flowPane.getChildren().clear(); // 清空当前GUI界面
                showAlert("习题已读取");
                displayAllEquationsFromDatabase();
            }
      });

      MenuItem checkMenuItem = new MenuItem("Check");

      checkMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 检查习题
                checkEquations();
            }
      });


      // View Accuracy按钮的点击事件监听器
      viewAccuracyButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 显示饼状图
                showAccuracyChart();
            }
      });



      Menu fileMenu = new Menu("File");
      Menu saveMenu = new Menu("SaveEquation");
      Menu readMenu = new Menu("ReadEquation");
      Menu checkMenu = new Menu("CheckEquation");

      fileMenu.getItems().addAll(generateMenuItem);
      saveMenu.getItems().add(saveMenuItem);
      readMenu.getItems().add(readMenuItem);
      checkMenu.getItems().add(checkMenuItem);

      MenuBar menuBar = new MenuBar();
      menuBar.getMenus().addAll(fileMenu);
      menuBar.getMenus().add(saveMenu);
      menuBar.getMenus().add(readMenu);
      menuBar.getMenus().add(checkMenu);

      flowPane.setHgap(50);
      flowPane.setVgap(30);
      flowPane.setPadding(new Insets(20));
      flowPane.setPrefSize(800, 560); // 设置 FlowPane 的大小

      BorderPane borderPane = new BorderPane();
      borderPane.setTop(menuBar);
      borderPane.setCenter(flowPane);
      HBox bottomBox = new HBox(10, viewAccuracyButton);
      borderPane.setBottom(bottomBox);

      Scene scene = new Scene(borderPane, 800, 640);
      stage.setTitle("口算习题薄");
      stage.setScene(scene);
      stage.show();

      


    }


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

    // 生成算式的方法
    public EquationCollection generateEquations(int n) {
      EquationCollection equationCollection = new EquationCollection();
      EquationCheckerOfRange equationChecker = new EquationCheckerOfRange(0, 100);
      equationCollection.generate(n, equationChecker);
      return equationCollection;
    }

    // 连接数据库的方法
    public void connectDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            DatabaseMetaData dbMeta = conn.getMetaData();
            System.out.println("当前用户:" + dbMeta.getUserName());
            System.out.println("驱动版本:" + dbMeta.getDriverVersion());
            System.out.println("MySQL版本:" + dbMeta.getDatabaseProductVersion());

            stmt = conn.createStatement();

            // 查询最大ID值
            ResultSet rs = stmt.executeQuery("SELECT MAX(id) FROM equationtable");
            if (rs.next()) {
                maxID = rs.getInt(1);
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void saveEquations() {
      Connection conn = null;
      PreparedStatement pstmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            for (Node node : flowPane.getChildren()) {
                if (node instanceof HBox) {
                  HBox equationBox = (HBox) node;
                  Label idLabel = (Label) equationBox.getChildren().get(0); // 获取算式ID标签
                  Label equationLabel = (Label) equationBox.getChildren().get(2);
                  TextField answerField = (TextField) equationBox.getChildren().get(3);

                  String equation = equationLabel.getText();
                  String answerText = answerField.getText();

                  // 检查答案字段是否为空
                  int answer = 0;
                  if (!answerText.isEmpty()) {
                        answer = Integer.parseInt(answerText);
                  }

                  // 计算正确结果
                  int result = calculateResult(equation);

                  // 保存到数据库
                  String sql = "INSERT INTO equationtable (id, Operand1, Operator, Operand2, Result) VALUES (?, ?, ?, ?, ?)";
                  pstmt = conn.prepareStatement(sql);
                  pstmt.setInt(1, Integer.parseInt(idLabel.getText())); // 将算式ID插入到数据库中
                  pstmt.setInt(2, getOperand1(equation));
                  pstmt.setString(3, getOperator(equation));
                  pstmt.setInt(4, getOperand2(equation));
                  pstmt.setInt(5, result);
                  pstmt.executeUpdate();
                }
            }

            System.out.println("算式保存成功!!!");
            showAlert("保存成功!");
      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (pstmt != null)
                  pstmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }



    private int calculateResult(String equation) {
      String[] parts = equation.split(" ");
      int operand1 = Integer.parseInt(parts);
      int operand2 = Integer.parseInt(parts);
      String operator = parts;

      int result = 0;
      switch (operator) {
            case "+":
                result = operand1 + operand2;
                break;
            case "-":
                result = operand1 - operand2;
                break;
            case "*":          //此处预设乘法和除法便于以后相应的添加功能
                result = operand1 * operand2;
                break;
            case "/":
                result = operand1 / operand2;
                break;
      }

      return result;
    }

    private int getOperand1(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private String getOperator(String equation) {
      String[] parts = equation.split(" ");
      return parts;
    }

    private int getOperand2(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private void showAlert(String message) {
      Alert alert = new Alert(Alert.AlertType.INFORMATION);
      alert.setTitle("提示信息");
      alert.setHeaderText(null);
      alert.setContentText(message);
      alert.showAndWait();
    }

    private void displayAllEquationsFromDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            stmt = conn.createStatement();

            ResultSet rs = stmt.executeQuery("SELECT * FROM equationtable");
            if (!rs.next()) {
                showAlert("当前题库为空");
            } else {
                do {
                  int id = rs.getInt("id");
                  String equation = id + "、 " + rs.getInt("Operand1") + " " + rs.getString("Operator") + " " +
                            rs.getInt("Operand2") + " = " + rs.getInt("Result");
                  Label equationLabel = new Label(equation);
                  flowPane.getChildren().add(equationLabel);
                } while (rs.next());
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void checkEquations() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      int incorrectAnswers = 0; // 答错题数

      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        equationBox.setStyle("-fx-background-color: #99ff99"); // 设置背景色为绿色
                        correctAnswers++;
                  } else { // 答案错误
                        equationBox.setStyle("-fx-background-color: #ff9999"); // 设置背景色为红色
                        incorrectAnswers++;
                  }
                }
            }
      }

      showAlert("您一共答对了 " + correctAnswers + " 题,总共提交了 " + totalEquations + " 题。");
      
    }

    private void showAccuracyChart() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        correctAnswers++;
                  }
                }
            }
      }
      // 创建一个饼状图数据
      double correctPercentage = (double) correctAnswers / totalEquations * 100;
      double incorrectPercentage = 100 - correctPercentage;
      ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList(
                new PieChart.Data("Correct (" + String.format("%.2f", correctPercentage)
                        + "%)", correctAnswers),
                new PieChart.Data("Incorrect (" + String.format("%.2f", incorrectPercentage)
                        + "%)", totalEquations - correctAnswers)
      );

      // 创建饼状图
      PieChart chart = new PieChart(pieChartData);
      chart.setTitle("Accuracy Chart");
      // 创建一个新的Stage来显示饼状图
      Stage chartStage = new Stage();
      chartStage.setScene(new Scene(chart, 600, 400));
      chartStage.show();

    }

}
添加功能,在GUI界面的右下角展示一个展示框,框内显示以下内容:
统计信息:(在最上方,意思是统计的以下内容进行展示)
总题数:(检查check执行后,已回答的题目计入总题数,未回答的题目不计入总数)
正确题数:
错误题数:(总题数,正确题数,错误题数放在一行里,中间适当间隔一定间距)
正确率:
错误率:(正确率和错误率放在一行里,中间适当间隔一定间距)
展示框整体要求离右边框和下边框各有20像素

FishC 发表于 2023-12-31 14:26:42

zqy173590939 发表于 2023-12-31 14:26
@FishC
package com.example.javafxmw;

import ga ...

要在GUI界面的右下角展示一个统计信息框,可以使用JavaFX的控件Label来实现。首先,在HelloApplication类中添加以下代码:

// 定义统计信息标签
Label totalLabel = new Label("总题数:0");
Label correctLabel = new Label("正确题数:0");
Label incorrectLabel = new Label("错误题数:0");
Label accuracyLabel = new Label("正确率:0%");
Label errorRateLabel = new Label("错误率:0%");

HBox statsBox = new HBox(10, totalLabel, correctLabel, incorrectLabel, accuracyLabel, errorRateLabel);
statsBox.setPadding(new Insets(0, 20, 20, 0)); // 设置边距

// 将统计信息标签添加到界面的底部布局
borderPane.setBottom(statsBox);

// 连接数据库时获取已有习题信息,并更新统计信息
displayAllEquationsFromDatabase();
updateStats();

// ...

// 更新统计信息的方法
private void updateStats() {
    int totalEquations = 0; // 总题数
    int correctAnswers = 0; // 答对题数
    int incorrectAnswers = 0; // 答错题数

    for (Node node : flowPane.getChildren()) {
      if (node instanceof HBox) {
            HBox equationBox = (HBox) node;
            Label equationLabel = (Label) equationBox.getChildren().get(2);
            TextField answerField = (TextField) equationBox.getChildren().get(3);
            String equation = equationLabel.getText();
            String answerText = answerField.getText();
            // 检查答案字段是否为空
            if (!answerText.isEmpty()) {
                totalEquations++;
                int userAnswer = Integer.parseInt(answerText);
                int result = calculateResult(equation);
                if (userAnswer == result) { // 答案正确
                  correctAnswers++;
                } else { // 答案错误
                  incorrectAnswers++;
                }
            }
      }
    }

    double accuracy = (double) correctAnswers / totalEquations * 100;
    double errorRate = 100 - accuracy;

    totalLabel.setText("总题数:" + totalEquations);
    correctLabel.setText("正确题数:" + correctAnswers);
    incorrectLabel.setText("错误题数:" + incorrectAnswers);
    accuracyLabel.setText("正确率:" + String.format("%.2f", accuracy) + "%");
    errorRateLabel.setText("错误率:" + String.format("%.2f", errorRate) + "%");
}

通过以上代码,你可以在GUI界面的右下角展示统计信息,包括总题数、正确题数、错误题数、正确率和错误率。每次答题后,通过调用`updateStats()`方法来更新统计信息。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zqy173590939 发表于 2023-12-31 14:37:10

@FishC
package com.example.javafxmw;

import gaijin3.*;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

import java.io.IOException;
import java.sql.*;
import java.util.Optional;

public class HelloApplication extends Application
{
    // 定义变量

    Button viewAccuracyButton = new Button("View Accuracy");


    FlowPane flowPane = new FlowPane();
    private int maxID = 0;

    @Override
    public void start(Stage stage) throws IOException {
      MenuItem generateMenuItem = new MenuItem("Generate");

      // 事件处理器代码
      generateMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 创建一个警示对话框
                TextInputDialog dialog = new TextInputDialog("5");
                dialog.setTitle("请输入算式数量");
                dialog.setHeaderText(null);
                dialog.setContentText("算式数量:");

                // 显示对话框,并获取用户输入的算式数量
                Optional<String> result = dialog.showAndWait();
                if (result.isPresent())
                {
                  int n = Integer.parseInt(result.get());

                  // 生成算式
                  EquationCollection equationCollection = generateEquations(n);

                  // 清空之前的内容
                  flowPane.getChildren().clear();

                  // 遍历算式集合并显示在GUI中
                  for (IEquation equation : equationCollection)
                  {
                        maxID++; // id自增
                        Label idLabel = new Label(String.valueOf(maxID)); // 获取当前最大ID,并将新的算式ID设为其加1
                        Label equationLabel = new Label(equation.toString());
                        TextField answerField = new TextField(); // 创建一个新的文本框
                        HBox equationBox = new HBox(10, idLabel, new Label("、"), equationLabel, answerField); // 将算式ID标签、顿号、算式标签和文本框放入水平布局
                        flowPane.getChildren().add(equationBox); // 将水平布局添加到 flowPane 中
                  }

                  // 连接数据库
                  connectDatabase();
                }
            }
      });

      MenuItem saveMenuItem = new MenuItem("Save");

      saveMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                saveEquations();
                connectDatabase();
            }
      });

      MenuItem readMenuItem = new MenuItem("Read");

      readMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                flowPane.getChildren().clear(); // 清空当前GUI界面
                showAlert("习题已读取");
                displayAllEquationsFromDatabase();
            }
      });

      MenuItem checkMenuItem = new MenuItem("Check");

      checkMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 检查习题
                checkEquations();
            }
      });


      // View Accuracy按钮的点击事件监听器
      viewAccuracyButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 显示饼状图
                showAccuracyChart();
            }
      });



      Menu fileMenu = new Menu("File");
      Menu saveMenu = new Menu("SaveEquation");
      Menu readMenu = new Menu("ReadEquation");
      Menu checkMenu = new Menu("CheckEquation");

      fileMenu.getItems().addAll(generateMenuItem);
      saveMenu.getItems().add(saveMenuItem);
      readMenu.getItems().add(readMenuItem);
      checkMenu.getItems().add(checkMenuItem);

      MenuBar menuBar = new MenuBar();
      menuBar.getMenus().addAll(fileMenu);
      menuBar.getMenus().add(saveMenu);
      menuBar.getMenus().add(readMenu);
      menuBar.getMenus().add(checkMenu);

      flowPane.setHgap(50);
      flowPane.setVgap(30);
      flowPane.setPadding(new Insets(20));
      flowPane.setPrefSize(800, 560); // 设置 FlowPane 的大小

      BorderPane borderPane = new BorderPane();
      borderPane.setTop(menuBar);
      borderPane.setCenter(flowPane);
      HBox bottomBox = new HBox(10, viewAccuracyButton);
      borderPane.setBottom(bottomBox);

      Scene scene = new Scene(borderPane, 800, 640);
      stage.setTitle("口算习题薄");
      stage.setScene(scene);
      stage.show();

      


    }


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

    // 生成算式的方法
    public EquationCollection generateEquations(int n) {
      EquationCollection equationCollection = new EquationCollection();
      EquationCheckerOfRange equationChecker = new EquationCheckerOfRange(0, 100);
      equationCollection.generate(n, equationChecker);
      return equationCollection;
    }

    // 连接数据库的方法
    public void connectDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            DatabaseMetaData dbMeta = conn.getMetaData();
            System.out.println("当前用户:" + dbMeta.getUserName());
            System.out.println("驱动版本:" + dbMeta.getDriverVersion());
            System.out.println("MySQL版本:" + dbMeta.getDatabaseProductVersion());

            stmt = conn.createStatement();

            // 查询最大ID值
            ResultSet rs = stmt.executeQuery("SELECT MAX(id) FROM equationtable");
            if (rs.next()) {
                maxID = rs.getInt(1);
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void saveEquations() {
      Connection conn = null;
      PreparedStatement pstmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            for (Node node : flowPane.getChildren()) {
                if (node instanceof HBox) {
                  HBox equationBox = (HBox) node;
                  Label idLabel = (Label) equationBox.getChildren().get(0); // 获取算式ID标签
                  Label equationLabel = (Label) equationBox.getChildren().get(2);
                  TextField answerField = (TextField) equationBox.getChildren().get(3);

                  String equation = equationLabel.getText();
                  String answerText = answerField.getText();

                  // 检查答案字段是否为空
                  int answer = 0;
                  if (!answerText.isEmpty()) {
                        answer = Integer.parseInt(answerText);
                  }

                  // 计算正确结果
                  int result = calculateResult(equation);

                  // 保存到数据库
                  String sql = "INSERT INTO equationtable (id, Operand1, Operator, Operand2, Result) VALUES (?, ?, ?, ?, ?)";
                  pstmt = conn.prepareStatement(sql);
                  pstmt.setInt(1, Integer.parseInt(idLabel.getText())); // 将算式ID插入到数据库中
                  pstmt.setInt(2, getOperand1(equation));
                  pstmt.setString(3, getOperator(equation));
                  pstmt.setInt(4, getOperand2(equation));
                  pstmt.setInt(5, result);
                  pstmt.executeUpdate();
                }
            }

            System.out.println("算式保存成功!!!");
            showAlert("保存成功!");
      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (pstmt != null)
                  pstmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }



    private int calculateResult(String equation) {
      String[] parts = equation.split(" ");
      int operand1 = Integer.parseInt(parts);
      int operand2 = Integer.parseInt(parts);
      String operator = parts;

      int result = 0;
      switch (operator) {
            case "+":
                result = operand1 + operand2;
                break;
            case "-":
                result = operand1 - operand2;
                break;
            case "*":          //此处预设乘法和除法便于以后相应的添加功能
                result = operand1 * operand2;
                break;
            case "/":
                result = operand1 / operand2;
                break;
      }

      return result;
    }

    private int getOperand1(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private String getOperator(String equation) {
      String[] parts = equation.split(" ");
      return parts;
    }

    private int getOperand2(String equation) {
      String[] parts = equation.split(" ");
      return Integer.parseInt(parts);
    }

    private void showAlert(String message) {
      Alert alert = new Alert(Alert.AlertType.INFORMATION);
      alert.setTitle("提示信息");
      alert.setHeaderText(null);
      alert.setContentText(message);
      alert.showAndWait();
    }

    private void displayAllEquationsFromDatabase() {
      Connection conn = null;
      Statement stmt = null;
      try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(
                  "jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                  "root", "Zqy173590939");

            stmt = conn.createStatement();

            ResultSet rs = stmt.executeQuery("SELECT * FROM equationtable");
            if (!rs.next()) {
                showAlert("当前题库为空");
            } else {
                do {
                  int id = rs.getInt("id");
                  String equation = id + "、 " + rs.getInt("Operand1") + " " + rs.getString("Operator") + " " +
                            rs.getInt("Operand2") + " = " + rs.getInt("Result");
                  Label equationLabel = new Label(equation);
                  flowPane.getChildren().add(equationLabel);
                } while (rs.next());
            }

      } catch (SQLException se) {
            se.printStackTrace();
      } catch (Exception e) {
            e.printStackTrace();
      } finally {
            try {
                if (stmt != null)
                  stmt.close();
                if (conn != null)
                  conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
      }
      System.out.println("Goodbye!");
    }

    private void checkEquations() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      int incorrectAnswers = 0; // 答错题数

      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        equationBox.setStyle("-fx-background-color: #99ff99"); // 设置背景色为绿色
                        correctAnswers++;
                  } else { // 答案错误
                        equationBox.setStyle("-fx-background-color: #ff9999"); // 设置背景色为红色
                        incorrectAnswers++;
                  }
                }
            }
      }

      showAlert("您一共答对了 " + correctAnswers + " 题,总共提交了 " + totalEquations + " 题。");
      
    }

    private void showAccuracyChart() {
      int totalEquations = 0; // 总题数
      int correctAnswers = 0; // 答对题数
      for (Node node : flowPane.getChildren()) {
            if (node instanceof HBox) {
                HBox equationBox = (HBox) node;
                Label equationLabel = (Label) equationBox.getChildren().get(2);
                TextField answerField = (TextField) equationBox.getChildren().get(3);
                String equation = equationLabel.getText();
                String answerText = answerField.getText();
                // 检查答案字段是否为空
                if (!answerText.isEmpty()) {
                  totalEquations++;
                  int userAnswer = Integer.parseInt(answerText);
                  int result = calculateResult(equation);
                  if (userAnswer == result) { // 答案正确
                        correctAnswers++;
                  }
                }
            }
      }
      // 创建一个饼状图数据
      double correctPercentage = (double) correctAnswers / totalEquations * 100;
      double incorrectPercentage = 100 - correctPercentage;
      ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList(
                new PieChart.Data("Correct (" + String.format("%.2f", correctPercentage)
                        + "%)", correctAnswers),
                new PieChart.Data("Incorrect (" + String.format("%.2f", incorrectPercentage)
                        + "%)", totalEquations - correctAnswers)
      );

      // 创建饼状图
      PieChart chart = new PieChart(pieChartData);
      chart.setTitle("Accuracy Chart");
      // 创建一个新的Stage来显示饼状图
      Stage chartStage = new Stage();
      chartStage.setScene(new Scene(chart, 600, 400));
      chartStage.show();

    }

}
添加功能,在GUI界面的右下角展示一个信息统计区域,使用textarea展示,区域内显示以下内容:
统计信息:(在最上方,意思是统计的以下内容进行展示)
总题数:(检查check执行后,已回答的题目计入总题数,未回答的题目不计入总数)
正确题数:
错误题数:(总题数,正确题数,错误题数放在一行里,中间适当间隔一定间距)
正确率:
错误率:(正确率和错误率放在一行里,中间适当间隔一定间距)
信息统计区域整体要求离右边框和下边框各有20像素

FishC 发表于 2023-12-31 14:42:43

zqy173590939 发表于 2023-12-31 14:37
@FishC
package com.example.javafxmw;

import ga ...

要在GUI界面的右下角展示一个信息统计区域,可以使用TextArea控件来实现。首先,在HelloApplication类中定义一个TextArea控件,并将其设置为只读:

TextArea infoTextArea = new TextArea();
infoTextArea.setEditable(false);

然后,在start方法中将infoTextArea添加到GUI界面的底部HBox布局中:

HBox bottomBox = new HBox(10, viewAccuracyButton, infoTextArea);
borderPane.setBottom(bottomBox);

接下来,在checkEquations方法中,计算总题数、正确题数和错误题数,并更新infoTextArea的内容:

private void checkEquations() {
    int totalEquations = 0; // 总题数
    int correctAnswers = 0; // 答对题数
    int incorrectAnswers = 0; // 答错题数

    for (Node node : flowPane.getChildren()) {
      if (node instanceof HBox) {
            HBox equationBox = (HBox) node;
            Label equationLabel = (Label) equationBox.getChildren().get(2);
            TextField answerField = (TextField) equationBox.getChildren().get(3);
            String equation = equationLabel.getText();
            String answerText = answerField.getText();
            // 检查答案字段是否为空
            if (!answerText.isEmpty()) {
                totalEquations++;
                int userAnswer = Integer.parseInt(answerText);
                int result = calculateResult(equation);
                if (userAnswer == result) { // 答案正确
                  equationBox.setStyle("-fx-background-color: #99ff99"); // 设置背景色为绿色
                  correctAnswers++;
                } else { // 答案错误
                  equationBox.setStyle("-fx-background-color: #ff9999"); // 设置背景色为红色
                  incorrectAnswers++;
                }
            }
      }
    }

    double correctPercentage = (double) correctAnswers / totalEquations * 100;
    double incorrectPercentage = (double) incorrectAnswers / totalEquations * 100;

    infoTextArea.setText("统计信息:\n" +
            "总题数:" + totalEquations + "\n" +
            "正确题数:" + correctAnswers + "\n" +
            "错误题数:" + incorrectAnswers + "\n" +
            "正确率:" + String.format("%.2f", correctPercentage) + "%\n" +
            "错误率:" + String.format("%.2f", incorrectPercentage) + "%");
}

最后,在showAccuracyChart方法中,也需要更新infoTextArea的内容:

private void showAccuracyChart() {
    int totalEquations = 0; // 总题数
    int correctAnswers = 0; // 答对题数
    for (Node node : flowPane.getChildren()) {
      if (node instanceof HBox) {
            HBox equationBox = (HBox) node;
            Label equationLabel = (Label) equationBox.getChildren().get(2);
            TextField answerField = (TextField) equationBox.getChildren().get(3);
            String equation = equationLabel.getText();
            String answerText = answerField.getText();
            // 检查答案字段是否为空
            if (!answerText.isEmpty()) {
                totalEquations++;
                int userAnswer = Integer.parseInt(answerText);
                int result = calculateResult(equation);
                if (userAnswer == result) { // 答案正确
                  correctAnswers++;
                }
            }
      }
    }
    // 创建一个饼状图数据
    double correctPercentage = (double) correctAnswers / totalEquations * 100;
    double incorrectPercentage = 100 - correctPercentage;

    infoTextArea.setText("统计信息:\n" +
            "总题数:" + totalEquations + "\n" +
            "正确题数:" + correctAnswers + "\n" +
            "错误题数:" + (totalEquations - correctAnswers) + "\n" +
            "正确率:" + String.format("%.2f", correctPercentage) + "%\n" +
            "错误率:" + String.format("%.2f", incorrectPercentage) + "%");

    // 创建饼状图并显示
    PieChart chart = new PieChart();
    ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList(
            new PieChart.Data("Correct", correctAnswers),
            new PieChart.Data("Incorrect", totalEquations - correctAnswers)
    );
    chart.setData(pieChartData);
    chart.setTitle("Accuracy Chart");

    // 创建一个新的Stage来显示饼状图
    Stage chartStage = new Stage();
    chartStage.setScene(new Scene(chart, 600, 400));
    chartStage.show();
}

这样,当用户点击Check按钮或View Accuracy按钮时,信息统计区域的内容会相应地更新。同时,根据题目回答情况,HBox布局的背景色也会改变。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zqy173590939 发表于 2023-12-31 15:14:06

FishC 发表于 2023-12-31 14:42
要在GUI界面的右下角展示一个信息统计区域,可以使用TextArea控件来实现。首先,在HelloApplication类 ...

想要限定textarea大小为500x150,应如何调整
页: 1 [2] 3 4 5
查看完整版本: Java实验完成