FishC 发表于 2023-12-31 17:20:17

zqy173590939 发表于 2023-12-31 17:19
@FishC
帮我写数据库课程设计,数据库使用MySQL,题 ...

对于教师岗位管理系统的设计,我们可以采用Java语言和MySQL数据库来实现。下面是一个简单的示例代码,可以帮助你开始:

首先,我们需要创建一个名为"Teacher"的Java类,来表示教师的基本信息:

public class Teacher {
    private String name;
    private String idCard;
    private String contact;
    private String email;
    private String job;
    private String researchLab;

    // 构造方法
    public Teacher(String name, String idCard, String contact, String email, String job, String researchLab) {
      this.name = name;
      this.idCard = idCard;
      this.contact = contact;
      this.email = email;
      this.job = job;
      this.researchLab = researchLab;
    }

    // Getter和Setter方法
    // ...

    // toString方法
    @Override
    public String toString() {
      return "姓名:" + name + "\n" +
                "身份证号:" + idCard + "\n" +
                "联系方式:" + contact + "\n" +
                "邮箱:" + email + "\n" +
                "工作时间:" + job + "\n" +
                "岗位:" + job + "\n" +
                "教研室信息:" + researchLab;
    }
}

然后,我们可以创建一个名为"TeacherManager"的Java类,来实现教师岗位的管理功能:

import java.util.ArrayList;
import java.util.List;

public class TeacherManager {
    private List<Teacher> teachers;

    public TeacherManager() {
      teachers = new ArrayList<>();
    }

    // 添加教师
    public void addTeacher(Teacher teacher) {
      teachers.add(teacher);
    }

    // 编辑教师信息
    public void editTeacher(String idCard, Teacher newTeacher) {
      for (int i = 0; i < teachers.size(); i++) {
            if (teachers.get(i).getIdCard().equals(idCard)) {
                teachers.set(i, newTeacher);
                break;
            }
      }
    }

    // 删除教师
    public void deleteTeacher(String idCard) {
      for (int i = 0; i < teachers.size(); i++) {
            if (teachers.get(i).getIdCard().equals(idCard)) {
                teachers.remove(i);
                break;
            }
      }
    }

    // 根据姓名查询教师
    public List<Teacher> searchByName(String name) {
      List<Teacher> result = new ArrayList<>();
      for (Teacher teacher : teachers) {
            if (teacher.getName().equals(name)) {
                result.add(teacher);
            }
      }
      return result;
    }

    // 根据身份证号查询教师
    public Teacher searchByIdCard(String idCard) {
      for (Teacher teacher : teachers) {
            if (teacher.getIdCard().equals(idCard)) {
                return teacher;
            }
      }
      return null;
    }

    // 获取所有教师
    public List<Teacher> getAllTeachers() {
      return teachers;
    }
}

接下来,我们可以创建一个简单的GUI界面来实现用户交互。你可以使用Swing或JavaFX等库来创建窗体、按钮等组件,并调用TeacherManager类的方法来进行教师岗位管理。由于篇幅有限,这里不提供完整的GUI代码,你可以根据需要自行实现。

最后,在MySQL数据库中创建一个名为"teachers"的表,包含与Teacher类对应的字段。你可以使用JDBC连接数据库,并编写相应的SQL语句来实现数据的持久化操作,例如插入、更新、删除和查询等。

希望以上代码能帮助到你开始设计教师岗位管理系统。由于题目要求较为复杂,还有很多细节需要进一步完善和实现。如果你遇到了具体的问题或需要更详细的帮助,请随时向我提问!

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

zqy173590939 发表于 2023-12-31 17:22:56

FishC 发表于 2023-12-31 17:20
对于教师岗位管理系统的设计,我们可以采用Java语言和MySQL数据库来实现。下面是一个简单的示例代码, ...

根据以上部分你写出的代码,补全完整的GUI部分代码

FishC 发表于 2023-12-31 17:24:10

zqy173590939 发表于 2023-12-31 17:22
根据以上部分你写出的代码,补全完整的GUI部分代码

以下是一个简单的GUI示例代码,使用Swing库来创建窗体和按钮,并与TeacherManager类进行交互:import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.util.List;public class TeacherManagerGUI {    private JFrame frame;    private JTextField nameTextField;    private JTextField idCardTextField;    private JTextField contactTextField;    private JTextField emailTextField;    private JTextField jobTextField;    private JTextField researchLabTextField;    private JTextArea resultTextArea;    private TeacherManager teacherManager;    // 构造方法    public TeacherManagerGUI() {      teacherManager = new TeacherManager();      initialize();    }    // 初始化界面    private void initialize() {      frame = new JFrame();      frame.setBounds(100, 100, 500, 400);      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);      frame.getContentPane().setLayout(null);      // 姓名标签      JLabel nameLabel = new JLabel("姓名:");      nameLabel.setBounds(20, 20, 60, 20);      frame.getContentPane().add(nameLabel);      // 姓名输入框      nameTextField = new JTextField();      nameTextField.setBounds(80, 20, 150, 20);      frame.getContentPane().add(nameTextField);      // 身份证号标签      JLabel idCardLabel = new JLabel("身份证号:");      idCardLabel.setBounds(20, 50, 60, 20);      frame.getContentPane().add(idCardLabel);      // 身份证号输入框      idCardTextField = new JTextField();      idCardTextField.setBounds(80, 50, 150, 20);      frame.getContentPane().add(idCardTextField);      // 其他输入框...      // 添加按钮      JButton addButton = new JButton("添加");      addButton.addActionListener(new ActionListener() {            public void actionPerformed(ActionEvent e) {                String name = nameTextField.getText();                String idCard = idCardTextField.getText();                String contact = contactTextField.getText();                String email = emailTextField.getText();                String job = jobTextField.getText();                String researchLab = researchLabTextField.getText();                Teacher teacher = new Teacher(name, idCard, contact, email, job, researchLab);                teacherManager.addTeacher(teacher);                resultTextArea.setText("添加成功!");            }      });      addButton.setBounds(20, 80, 100, 20);      frame.getContentPane().add(addButton);      // 查询按钮      JButton searchButton = new JButton("查询");      searchButton.addActionListener(new ActionListener() {            public void actionPerformed(ActionEvent e) {                String name = nameTextField.getText();                List<Teacher> teachers = teacherManager.searchByName(name);                StringBuilder result = new StringBuilder();                for (Teacher teacher : teachers) {                  result.append(teacher.toString()).append("\n\n");                }                resultTextArea.setText(result.toString());            }      });      searchButton.setBounds(130, 80, 100, 20);      frame.getContentPane().add(searchButton);      // 结果文本区域      resultTextArea = new JTextArea();      resultTextArea.setBounds(20, 120, 400, 200);      frame.getContentPane().add(resultTextArea);    }    // 启动程序    public void start() {      EventQueue.invokeLater(new Runnable() {            public void run() {                try {                  TeacherManagerGUI window = new TeacherManagerGUI();                  window.frame.setVisible(true);                } catch (Exception e) {                  e.printStackTrace();                }            }      });    }}然后,可以在main方法中创建TeacherManagerGUI对象并调用其start方法来启动程序:public static void main(String[] args) {    TeacherManagerGUI teacherManagerGUI = new TeacherManagerGUI();    teacherManagerGUI.start();}请注意,以上代码只是一个简单示例,你可以根据实际需求自行扩展界面和功能。希望这能对你有所帮助!

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

zqy173590939 发表于 2023-12-31 20:49:02

@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
{
    // 定义全局变量
    //定义一个TextArea控件作为全局变量
    TextArea infoTextArea = new TextArea();

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

    FlowPane flowPane = new FlowPane();
    ScrollPane scrollPane = new ScrollPane();// 创建一个滚动面板对象
    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) {
                generateEquation();
            }
      });

      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);

      //为了解决题目生成或多flowpane没有拖动条无法显示的问题
      // 将FlowPane放在一个ScrollPane中
      scrollPane.setContent(flowPane);// 设置滚动面板的内容为 flowPane,即将 flowPane 放入滚动面板中
      scrollPane.setFitToHeight(true);// 可以让滚动面板的高度自适应内容的高度
      borderPane.setCenter(scrollPane); // 将ScrollPane放置在中心位置

      HBox bottomBox = new HBox(10, viewAccuracyButton);
      HBox.setMargin(viewAccuracyButton, new Insets(50, 0, 20, 140));
      borderPane.setBottom(bottomBox);

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

      infoTextArea.setPrefSize(400, 110);
      //将TextArea控件其设置为只读
      infoTextArea.setEditable(false);

      HBox showbottomBox = new HBox(140, viewAccuracyButton, infoTextArea);
      HBox.setMargin(infoTextArea, new Insets(20, 0, 20, 0));
      borderPane.setBottom(showbottomBox);


    }


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

    //为了使generate的事件处理器更美观特意拉出了这个类
    public EquationCollection generateEquation() {
      // 创建一个警示对话框
      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();
      }
      return null;
    }

    // 生成算式的方法
    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++;
                  }
                }
            }
      }

      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) + "%");
    }

    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();
    }

}
为Delete by serial number按钮和Delete all按钮创建事件处理器,点击Delete by serial number按钮后,调用读取方法,读取数据库中所有题目展示到界面中,然后弹出警示对话框,警示对话框内有两个textfield,让用户输入ID范围,输入后点击确定则从数据库删除输入ID范围的算数式,并使用警示对话框弹出删除成功;如果输入超出范围则用警示对话框提示超出范围。点击Delete all按钮则直接删除数据库中所有算数式,并使用警示对话框展示删除成功。

FishC 发表于 2023-12-31 20:49:40

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

import ga ...

首先,我们需要为"Delete by serial number"按钮和"Delete all"按钮创建事件处理器。事件处理器会在用户点击按钮时执行相应的操作。

下面是实现这两个按钮事件处理器的代码:

// Delete by serial number按钮的点击事件监听器
deleteBySerialNumberButton.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
      // 读取数据库中的所有题目并展示到界面上
      flowPane.getChildren().clear();
      displayAllEquationsFromDatabase();

      // 创建一个对话框
      Dialog<Pair<String, String>> dialog = new Dialog<>();
      dialog.setTitle("删除算数式");
      dialog.setHeaderText(null);

      // 设置对话框的图标
      Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
      stage.getIcons().add(new Image("/path/to/your/icon.png"));

      // 设置对话框的按钮
      ButtonType deleteButtonType = new ButtonType("Delete", ButtonBar.ButtonData.OK_DONE);
      dialog.getDialogPane().getButtonTypes().addAll(deleteButtonType, ButtonType.CANCEL);

      // 创建输入字段
      TextField startTextField = new TextField();
      TextField endTextField = new TextField();

      // 将输入字段添加到对话框的内容面板中
      GridPane gridPane = new GridPane();
      gridPane.setHgap(10);
      gridPane.setVgap(10);
      gridPane.addRow(0, new Label("起始ID: "), startTextField);
      gridPane.addRow(1, new Label("结束ID: "), endTextField);
      dialog.getDialogPane().setContent(gridPane);

      // 设置按钮点击事件处理器
      Node deleteButton = dialog.getDialogPane().lookupButton(deleteButtonType);
      deleteButton.setDisable(true); // 默认禁用删除按钮

      startTextField.textProperty().addListener((observable, oldValue, newValue) -> {
            deleteButton.setDisable(newValue.trim().isEmpty()); // 当输入字段为空时禁用删除按钮
      });

      // 显示对话框并等待用户操作
      Optional<Pair<String, String>> result = dialog.showAndWait();

      // 处理用户点击确定按钮的情况
      result.ifPresent(pair -> {
            int startID = Integer.parseInt(pair.getKey());
            int endID = Integer.parseInt(pair.getValue());

            // 检查输入ID范围是否合法
            if (startID >= 1 && endID >= startID && endID <= maxID) {
                // 删除数据库中指定ID范围的算术式
                deleteEquations(startID, endID);

                // 清空界面上删除的算术式
                for (Node node : flowPane.getChildren()) {
                  if (node instanceof HBox) {
                        HBox equationBox = (HBox) node;
                        Label idLabel = (Label) equationBox.getChildren().get(0);
                        int id = Integer.parseInt(idLabel.getText());

                        if (id >= startID && id <= endID) {
                            flowPane.getChildren().remove(node);
                        }
                  }
                }

                showAlert("算术式删除成功!");
            } else {
                showAlert("输入的ID范围不合法!");
            }
      });
    }
});

// Delete all按钮的点击事件监听器
deleteAllButton.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
      // 删除数据库中的所有算术式
      deleteAllEquations();

      // 清空界面上的所有算术式
      flowPane.getChildren().clear();

      showAlert("所有算术式删除成功!");
    }
});

然后,我们需要实现`deleteEquations`方法和`deleteAllEquations`方法来删除数据库中的算术式。以下是实现这两个方法的代码:

// 删除数据库中指定ID范围的算术式
private void deleteEquations(int startID, int endID) {
    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");

      String sql = "DELETE FROM equationtable WHERE id >= ? AND id <= ?";
      pstmt = conn.prepareStatement(sql);
      pstmt.setInt(1, startID);
      pstmt.setInt(2, endID);
      pstmt.executeUpdate();
    } 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 void deleteAllEquations() {
    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();

      String sql = "DELETE FROM equationtable";
      stmt.executeUpdate(sql);
    } 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!");
}

最后,我们需要添加一个新的按钮`deleteBySerialNumberButton`和一个新的按钮`deleteAllButton`来代表"Delete by serial number"按钮和"Delete all"按钮。以下是相应的代码:

Button deleteBySerialNumberButton = new Button("Delete by serial number");
Button deleteAllButton = new Button("Delete all");

HBox deleteButtonBox = new HBox(10, deleteBySerialNumberButton, deleteAllButton);
deleteButtonBox.setPadding(new Insets(20));
borderPane.setBottom(deleteButtonBox);

将上述代码添加到`start`方法的最后一行,就可以在界面上添加"Delete by serial number"按钮和"Delete all"按钮,并为其添加事件处理器了。

希望以上解答对你有帮助!如果还有其他问题,请随时提问。

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

zqy173590939 发表于 2023-12-31 21:02:52

FishC 发表于 2023-12-31 20:49
首先,我们需要为"Delete by serial number"按钮和"Delete all"按钮创建事件处理器。事件处理器会在用 ...

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: class javafx.scene.control.ButtonType cannot be cast to class javafx.util.Pair (javafx.scene.control.ButtonType and javafx.util.Pair are in unnamed module of loader 'app')
        at java.base/java.util.Optional.ifPresent(Optional.java:178)
        at com.example.javafxmw.HelloApplication$6.handle(HelloApplication.java:137)
        at com.example.javafxmw.HelloApplication$6.handle(HelloApplication.java:93)
        at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
        at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
        at javafx.event.Event.fireEvent(Event.java:198)
        at javafx.scene.control.MenuItem.fire(MenuItem.java:459)
        at com.sun.javafx.scene.control.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1385)
        at com.sun.javafx.scene.control.ContextMenuContent$MenuItemContainer.lambda$createChildren$12(ContextMenuContent.java:1338)
        at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
        at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
        at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
        at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
        at javafx.event.Event.fireEvent(Event.java:198)
        at javafx.scene.Scene$MouseHandler.process(Scene.java:3897)
        at javafx.scene.Scene.processMouseEvent(Scene.java:1878)
        at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2623)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
        at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
        at com.sun.glass.ui.View.handleMouseEvent(View.java:557)
        at com.sun.glass.ui.View.notifyMouse(View.java:943)
        at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
        at java.base/java.lang.Thread.run(Thread.java:842)
出现了以下问题,请修正

FishC 发表于 2023-12-31 21:02:57

zqy173590939 发表于 2023-12-31 21:02
Exception in thread "JavaFX Application Thread" ja ...

出现了ClassCastException,因为JavaFX的ButtonType和Pair属于不同的类,无法直接进行转换。要解决这个问题,我们可以使用一个自定义类来存储起

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

zqy173590939 发表于 2023-12-31 21:08:52

FishC 发表于 2023-12-31 20:49
首先,我们需要为"Delete by serial number"按钮和"Delete all"按钮创建事件处理器。事件处理器会在用 ...

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: class javafx.scene.control.ButtonType cannot be cast to class javafx.util.Pair (javafx.scene.control.ButtonType and javafx.util.Pair are in unnamed module of loader 'app')
      at java.base/java.util.Optional.ifPresent(Optional.java:178)
      at com.example.javafxmw.HelloApplication$6.handle(HelloApplication.java:137)
      at com.example.javafxmw.HelloApplication$6.handle(HelloApplication.java:93)
      at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
      at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
      at javafx.event.Event.fireEvent(Event.java:198)
      at javafx.scene.control.MenuItem.fire(MenuItem.java:459)
      at com.sun.javafx.scene.control.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1385)
      at com.sun.javafx.scene.control.ContextMenuContent$MenuItemContainer.lambda$createChildren$12(ContextMenuContent.java:1338)
      at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
      at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
      at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
      at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
      at javafx.event.Event.fireEvent(Event.java:198)
      at javafx.scene.Scene$MouseHandler.process(Scene.java:3897)
      at javafx.scene.Scene.processMouseEvent(Scene.java:1878)
      at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2623)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
      at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
      at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
      at com.sun.glass.ui.View.handleMouseEvent(View.java:557)
      at com.sun.glass.ui.View.notifyMouse(View.java:943)
      at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
      at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
      at java.base/java.lang.Thread.run(Thread.java:842)
出现了以下问题,请修正

FishC 发表于 2023-12-31 21:09:03

zqy173590939 发表于 2023-12-31 21:08
Exception in thread "JavaFX Application Thread" ja ...

问题出在代码的这一行:

```
result.ifPresent(pair -> {
    int startID = Integer.parseInt(pair.getKey());
    int endID = Integer.parseInt(pair.getValue());
    // 检查输入ID范围是否

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

zqy173590939 发表于 2023-12-31 21:09:55

FishC 发表于 2023-12-31 20:49
首先,我们需要为"Delete by serial number"按钮和"Delete all"按钮创建事件处理器。事件处理器会在用 ...

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: class javafx.scene.control.ButtonType cannot be cast to class javafx.util.Pair (javafx.scene.control.ButtonType and javafx.util.Pair are in unnamed module of loader 'app')
      at java.base/java.util.Optional.ifPresent(Optional.java:178)
      at com.example.javafxmw.HelloApplication$6.handle(HelloApplication.java:137)
      at com.example.javafxmw.HelloApplication$6.handle(HelloApplication.java:93)
      at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
      at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
      at javafx.event.Event.fireEvent(Event.java:198)
      at javafx.scene.control.MenuItem.fire(MenuItem.java:459)
      at com.sun.javafx.scene.control.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1385)
      at com.sun.javafx.scene.control.ContextMenuContent$MenuItemContainer.lambda$createChildren$12(ContextMenuContent.java:1338)
      at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
      at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
      at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
      at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
      at javafx.event.Event.fireEvent(Event.java:198)
      at javafx.scene.Scene$MouseHandler.process(Scene.java:3897)
      at javafx.scene.Scene.processMouseEvent(Scene.java:1878)
      at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2623)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
      at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
      at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
      at com.sun.glass.ui.View.handleMouseEvent(View.java:557)
      at com.sun.glass.ui.View.notifyMouse(View.java:943)
      at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
      at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
      at java.base/java.lang.Thread.run(Thread.java:842)
修正此问题,请给出修改后的代码

FishC 发表于 2023-12-31 21:10:03

zqy173590939 发表于 2023-12-31 21:09
Exception in thread "JavaFX Application Thread" ja ...

您好,根据报错信息,问题出在将ButtonType转换为Pair的地方。在JavaFX中,ButtonType是用于表示对话框的按钮类型的类,而不是用来表示键

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

zqy173590939 发表于 2023-12-31 21:12:18

@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.image.Image;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Pair;

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

public class HelloApplication extends Application
{
    // 定义全局变量
    //定义一个TextArea控件作为全局变量
    TextArea infoTextArea = new TextArea();

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

    FlowPane flowPane = new FlowPane();
    ScrollPane scrollPane = new ScrollPane();// 创建一个滚动面板对象
    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) {
                generateEquation();
            }
      });

      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();
            }
      });

      MenuItem deleteMenuItem = new MenuItem("Delete by serial number");

      

      MenuItem deleteMenuItem1 = new MenuItem("Delete all");

      // Delete all按钮的点击事件监听器
      deleteMenuItem1.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 删除数据库中的所有算术式
                deleteAllEquations();

                // 清空界面上的所有算术式
                flowPane.getChildren().clear();

                showAlert("所有算术式删除成功!");
            }
      });

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

      fileMenu.getItems().addAll(generateMenuItem);
      saveMenu.getItems().add(saveMenuItem);
      readMenu.getItems().add(readMenuItem);
      checkMenu.getItems().add(checkMenuItem);
      deleteMenu.getItems().addAll(deleteMenuItem,deleteMenuItem1);

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

      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);

      //为了解决题目生成或多flowpane没有拖动条无法显示的问题
      // 将FlowPane放在一个ScrollPane中
      scrollPane.setContent(flowPane);// 设置滚动面板的内容为 flowPane,即将 flowPane 放入滚动面板中
      scrollPane.setFitToHeight(true);// 可以让滚动面板的高度自适应内容的高度
      borderPane.setCenter(scrollPane); // 将ScrollPane放置在中心位置

      HBox bottomBox = new HBox(10, viewAccuracyButton);
      HBox.setMargin(viewAccuracyButton, new Insets(50, 0, 20, 140));
      borderPane.setBottom(bottomBox);

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

      infoTextArea.setPrefSize(400, 110);
      //将TextArea控件其设置为只读
      infoTextArea.setEditable(false);

      HBox showbottomBox = new HBox(140, viewAccuracyButton, infoTextArea);
      HBox.setMargin(infoTextArea, new Insets(20, 0, 20, 0));
      borderPane.setBottom(showbottomBox);


    }


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

    //为了使generate的事件处理器更美观特意拉出了这个类
    public EquationCollection generateEquation() {
      // 创建一个警示对话框
      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();
      }
      return null;
    }

    // 生成算式的方法
    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++;
                  }
                }
            }
      }

      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) + "%");
    }

    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();
    }

   

    // 删除数据库中的所有算术式
    private void deleteAllEquations() {
      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();

            String sql = "DELETE FROM equationtable";
            stmt.executeUpdate(sql);
      } 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!");
    }



}
为Delete by serial number按钮创建事件处理器,点击Delete by serial number按钮后,调用读取方法,读取数据库中所有题目展示到界面中,然后弹出警示对话框,警示对话框内有两个textfield,让用户输入ID范围,输入后点击确定则从数据库删除输入ID范围的算数式,并使用警示对话框弹出删除成功;如果输入超出范围则用警示对话框提示超出范围。

FishC 发表于 2023-12-31 21:12:38

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

import ga ...

首先,我们需要为 "Delete by serial number" 按钮创建一个事件处理器。在这个事件处理器中,我们需要调用 `displayAllEquationsFromDatabase` 方法,将数据库中的算术式显示到界面上。然后,我们可以使用 `TextInputDialog` 弹出警示对话框,让用户输入要删除的算术式的ID范围。最后,根据用户的输入,在数据库中删除相应的算术式,并显示删除成功的警示对话框。

下面是完整的代码实现:

// 定义 Delete by serial number 按钮的点击事件监听器
deleteMenuItem.setOnAction(new EventHandler() {
    @Override
    public void handle(ActionEvent event) {
      // 显示数据库中的所有算术式
      flowPane.getChildren().clear();
      displayAllEquationsFromDatabase();

      // 创建一个警示对话框并设置标题和头部文本
      TextInputDialog dialog = new TextInputDialog();
      dialog.setTitle("删除算术式");
      dialog.setHeaderText("请输入要删除的算术式的ID范围(格式:start-end)");

      // 获取用户输入的起始ID和结束ID
      Optional<String> result = dialog.showAndWait();
      if (result.isPresent()) {
            String[] ids = result.get().split("-");
            int startID = Integer.parseInt(ids);
            int endID = Integer.parseInt(ids);

            // 删除ID在范围内的算术式
            deleteEquationsByRange(startID, endID);
      }
    }
});

// 删除数据库中范围内的算术式的方法
private void deleteEquationsByRange(int startID, int endID) {
    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 WHERE id >= " + startID + " AND id <= " + endID);
      if (rs.next()) {
            // 逐个删除算术式
            do {
                int id = rs.getInt("id");
                stmt.executeUpdate("DELETE FROM equationtable WHERE id = " + id);
            } while (rs.next());

            showAlert("算术式删除成功!");
      } else {
            showAlert("没有找到符合范围条件的算术式!");
      }
    } 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!");
}

请注意,上述代码仅实现了删除数据库中范围内的算术式的功能,对应的界面显示部分需要根据具体情况进行调整。另外,要确保数据库表名和字段名与代码中的一致,否则需要进行相应的修改。

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

zqy173590939 发表于 2023-12-31 21:16:57

FishC 发表于 2023-12-31 21:12
首先,我们需要为 "Delete by serial number" 按钮创建一个事件处理器。在这个事件处理器中,我们需要 ...

java.sql.SQLException: Operation not allowed after ResultSet closed
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:130)
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:98)
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:90)
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:64)
        at com.mysql.cj.jdbc.result.ResultSetImpl.checkClosed(ResultSetImpl.java:485)
        at com.mysql.cj.jdbc.result.ResultSetImpl.next(ResultSetImpl.java:1802)
        at com.example.javafxmw.HelloApplication.deleteEquationsByRange(HelloApplication.java:533)
        at com.example.javafxmw.HelloApplication$6.handle(HelloApplication.java:113)
        at com.example.javafxmw.HelloApplication$6.handle(HelloApplication.java:93)
        at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
        at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
        at javafx.event.Event.fireEvent(Event.java:198)
        at javafx.scene.control.MenuItem.fire(MenuItem.java:459)
        at com.sun.javafx.scene.control.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1385)
        at com.sun.javafx.scene.control.ContextMenuContent$MenuItemContainer.lambda$createChildren$12(ContextMenuContent.java:1338)
        at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
        at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
        at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
        at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
        at javafx.event.Event.fireEvent(Event.java:198)
        at javafx.scene.Scene$MouseHandler.process(Scene.java:3897)
        at javafx.scene.Scene.processMouseEvent(Scene.java:1878)
        at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2623)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
        at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
        at com.sun.glass.ui.View.handleMouseEvent(View.java:557)
        at com.sun.glass.ui.View.notifyMouse(View.java:943)
        at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
        at java.base/java.lang.Thread.run(Thread.java:842)
出现了以上问题,请改正,给出改正后代码

FishC 发表于 2023-12-31 21:17:05

zqy173590939 发表于 2023-12-31 21:16
java.sql.SQLException: Operation not allowed after ...

在 `deleteEquationsByRange` 方法中,您需要关闭 ResultSet 对象,以确保它不会在查询结束后继续保持打开状态。请尝试在执行完数据库查询后立

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

zqy173590939 发表于 2023-12-31 21:27:18

@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.image.Image;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Pair;

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

public class HelloApplication extends Application
{
    // 定义全局变量
    //定义一个TextArea控件作为全局变量
    TextArea infoTextArea = new TextArea();

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

    FlowPane flowPane = new FlowPane();
    ScrollPane scrollPane = new ScrollPane();// 创建一个滚动面板对象
    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) {
                generateEquation();
            }
      });

      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();
            }
      });

      MenuItem deleteMenuItem = new MenuItem("Delete by serial number");

      

      MenuItem deleteMenuItem1 = new MenuItem("Delete all");

      // Delete all按钮的点击事件监听器
      deleteMenuItem1.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 删除数据库中的所有算术式
                deleteAllEquations();

                // 清空界面上的所有算术式
                flowPane.getChildren().clear();

                showAlert("所有算术式删除成功!");
            }
      });

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

      fileMenu.getItems().addAll(generateMenuItem);
      saveMenu.getItems().add(saveMenuItem);
      readMenu.getItems().add(readMenuItem);
      checkMenu.getItems().add(checkMenuItem);
      deleteMenu.getItems().addAll(deleteMenuItem,deleteMenuItem1);

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

      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);

      //为了解决题目生成或多flowpane没有拖动条无法显示的问题
      // 将FlowPane放在一个ScrollPane中
      scrollPane.setContent(flowPane);// 设置滚动面板的内容为 flowPane,即将 flowPane 放入滚动面板中
      scrollPane.setFitToHeight(true);// 可以让滚动面板的高度自适应内容的高度
      borderPane.setCenter(scrollPane); // 将ScrollPane放置在中心位置

      HBox bottomBox = new HBox(10, viewAccuracyButton);
      HBox.setMargin(viewAccuracyButton, new Insets(50, 0, 20, 140));
      borderPane.setBottom(bottomBox);

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

      infoTextArea.setPrefSize(400, 110);
      //将TextArea控件其设置为只读
      infoTextArea.setEditable(false);

      HBox showbottomBox = new HBox(140, viewAccuracyButton, infoTextArea);
      HBox.setMargin(infoTextArea, new Insets(20, 0, 20, 0));
      borderPane.setBottom(showbottomBox);


    }


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

    //为了使generate的事件处理器更美观特意拉出了这个类
    public EquationCollection generateEquation() {
      // 创建一个警示对话框
      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();
      }
      return null;
    }

    // 生成算式的方法
    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++;
                  }
                }
            }
      }

      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) + "%");
    }

    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();
    }

   

    // 删除数据库中的所有算术式
    private void deleteAllEquations() {
      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();

            String sql = "DELETE FROM equationtable";
            stmt.executeUpdate(sql);
      } 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!");
    }



}
修改代码,为Delete by serial number按钮创建事件处理器,点击Delete by serial number按钮后,调用读取方法,读取数据库中所有题目展示到界面中,然后弹出警示对话框,警示对话框内有两个textfield,让用户输入ID范围,输入后点击确定则从数据库删除输入ID范围的算数式,并使用警示对话框弹出删除成功;如果输入超出范围则用警示对话框提示超出范围,如果输入的范围首尾ID都存在,但是,中间缺失了部分序号,则跳过那些确实的需要,保证删除可以正常执行;如果输入的ID范围内,数据库有多条匹配,则把匹配上的全部删除。

FishC 发表于 2023-12-31 21:27:44

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

import ga ...

package com.example.javafxmw;

import gaijin3.EquationCollection;
import gaijin3.IEquation;
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.image.Image;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Pair;

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

public class HelloApplication extends Application {
    // 定义全局变量
    //定义一个TextArea控件作为全局变量
    TextArea infoTextArea = new TextArea();

    Button viewAccuracyButton = new Button("View Accuracy");
    Button deleteBySerialNumberButton = new Button("Delete by serial number");

    FlowPane flowPane = new FlowPane();
    ScrollPane scrollPane = new ScrollPane();// 创建一个滚动面板对象
    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) {
                generateEquation();
            }
      });

      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();
            }
      });

      // Delete by serial number按钮的点击事件监听器
      deleteBySerialNumberButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 删除算术式
                deleteEquationsBySerialNumber();
            }
      });

      MenuItem deleteMenuItem1 = new MenuItem("Delete all");

      // Delete all按钮的点击事件监听器
      deleteMenuItem1.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 删除数据库中的所有算术式
                deleteAllEquations();

                // 清空界面上的所有算术式
                flowPane.getChildren().clear();

                showAlert("所有算术式删除成功!");
            }
      });

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

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

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

      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);

      //为了解决题目生成或多flowpane没有拖动条无法显示的问题
      // 将FlowPane放在一个ScrollPane中
      scrollPane.setContent(flowPane);// 设置滚动面板的内容为 flowPane,即将 flowPane 放入滚动面板中
      scrollPane.setFitToHeight(true);// 可以让滚动面板的高度自适应内容的高度
      borderPane.setCenter(scrollPane); // 将ScrollPane放置在中心位置

      HBox bottomBox = new HBox(10, viewAccuracyButton, deleteBySerialNumberButton);
      HBox.setMargin(viewAccuracyButton, new Insets(50, 0, 20, 140));
      HBox.setMargin(deleteBySerialNumberButton, new Insets(50, 0, 20, 0));
      borderPane.setBottom(bottomBox);

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

      infoTextArea.setPrefSize(400, 110);
      //将TextArea控件其设置为只读
      infoTextArea.setEditable(false);

      HBox showbottomBox = new HBox(140, viewAccuracyButton, deleteBySerialNumberButton, infoTextArea);
      HBox.setMargin(infoTextArea, new Insets(20, 0, 20, 0));
      borderPane.setBottom(showbottomBox);


    }

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

    //为了使generate的事件处理器更美观特意拉出了这个方法
    public EquationCollection generateEquation() {
      // 创建一个警示对话框
      TextInputDialog dialog = new TextInputDialog("5");

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

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

@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.image.Image;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Pair;

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

public class HelloApplication extends Application
{
    // 定义全局变量
    //定义一个TextArea控件作为全局变量
    TextArea infoTextArea = new TextArea();

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

    FlowPane flowPane = new FlowPane();
    ScrollPane scrollPane = new ScrollPane();// 创建一个滚动面板对象
    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) {
                generateEquation();
            }
      });

      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();
            }
      });

      MenuItem deleteMenuItem = new MenuItem("Delete by serial number");

      

      MenuItem deleteMenuItem1 = new MenuItem("Delete all");

      // Delete all按钮的点击事件监听器
      deleteMenuItem1.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 删除数据库中的所有算术式
                deleteAllEquations();

                // 清空界面上的所有算术式
                flowPane.getChildren().clear();

                showAlert("所有算术式删除成功!");
            }
      });

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

      fileMenu.getItems().addAll(generateMenuItem);
      saveMenu.getItems().add(saveMenuItem);
      readMenu.getItems().add(readMenuItem);
      checkMenu.getItems().add(checkMenuItem);
      deleteMenu.getItems().addAll(deleteMenuItem,deleteMenuItem1);

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

      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);

      //为了解决题目生成或多flowpane没有拖动条无法显示的问题
      // 将FlowPane放在一个ScrollPane中
      scrollPane.setContent(flowPane);// 设置滚动面板的内容为 flowPane,即将 flowPane 放入滚动面板中
      scrollPane.setFitToHeight(true);// 可以让滚动面板的高度自适应内容的高度
      borderPane.setCenter(scrollPane); // 将ScrollPane放置在中心位置

      HBox bottomBox = new HBox(10, viewAccuracyButton);
      HBox.setMargin(viewAccuracyButton, new Insets(50, 0, 20, 140));
      borderPane.setBottom(bottomBox);

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

      infoTextArea.setPrefSize(400, 110);
      //将TextArea控件其设置为只读
      infoTextArea.setEditable(false);

      HBox showbottomBox = new HBox(140, viewAccuracyButton, infoTextArea);
      HBox.setMargin(infoTextArea, new Insets(20, 0, 20, 0));
      borderPane.setBottom(showbottomBox);


    }


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

    //为了使generate的事件处理器更美观特意拉出了这个类
    public EquationCollection generateEquation() {
      // 创建一个警示对话框
      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();
      }
      return null;
    }

    // 生成算式的方法
    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++;
                  }
                }
            }
      }

      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) + "%");
    }

    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();
    }

   

    // 删除数据库中的所有算术式
    private void deleteAllEquations() {
      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();

            String sql = "DELETE FROM equationtable";
            stmt.executeUpdate(sql);
      } 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!");
    }



}
修改代码,为Delete by serial number按钮创建事件处理器,点击Delete by serial number按钮后,调用读取方法,读取数据库中所有题目展示到界面中,然后弹出警示对话框,警示对话框内有两个textfield,让用户输入ID范围,输入后点击确定则从数据库删除输入ID范围的算数式,并使用警示对话框弹出删除成功;如果输入超出范围则用警示对话框提示超出范围,如果输入的范围首尾ID都存在,但是,中间缺失了部分序号,则跳过那些确实的需要,保证删除可以正常执行;如果输入的ID范围内,数据库有多条匹配,则把匹配上的全部删除。
给出需要添加和修改的部分即可。

FishC 发表于 2023-12-31 21:28:44

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

import ga ...

首先,需要在deleteMenu中添加一个新的MenuItem,命名为deleteMenuItem2:

MenuItem deleteMenuItem2 = new MenuItem("Delete by range");

然后,在deleteMenuItem2的点击事件处理器中调用读取方法displayAllEquationsFromDatabase(),并弹出警示对话框让用户输入ID范围:

deleteMenuItem2.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
      // 读取数据库中所有题目展示到界面中
      flowPane.getChildren().clear();
      displayAllEquationsFromDatabase();
      
      // 创建一个警示对话框
      Dialog<Pair<String, String>> dialog = new Dialog<>();
      dialog.setTitle("删除算术式范围");
      dialog.setHeaderText(null);

      // 设置对话框的图标
      Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
      stage.getIcons().add(new Image("file:icon.png"));

      // 设置对话框的按钮
      ButtonType deleteButtonType = new ButtonType("删除", ButtonBar.ButtonData.OK_DONE);
      dialog.getDialogPane().getButtonTypes().addAll(deleteButtonType, ButtonType.CANCEL);

      // 创建并设置对话框的内容
      GridPane grid = new GridPane();
      grid.setHgap(10);
      grid.setVgap(10);
      grid.setPadding(new Insets(20, 150, 10, 10));

      TextField startIDTextField = new TextField();
      TextField endIDTextField = new TextField();

      grid.add(new Label("起始ID:"), 0, 0);
      grid.add(startIDTextField, 1, 0);
      grid.add(new Label("结束ID:"), 2, 0);
      grid.add(endIDTextField, 3, 0);

      dialog.getDialogPane().setContent(grid);

      // 点击删除按钮时的逻辑
      dialog.setResultConverter(dialogButton -> {
            if (dialogButton == deleteButtonType) {
                int startID = Integer.parseInt(startIDTextField.getText());
                int endID = Integer.parseInt(endIDTextField.getText());

                // 删除数据库中匹配的算术式
                deleteEquationsByRange(startID, endID);

                // 清空界面上的匹配的算术式
                for (Node node : flowPane.getChildren()) {
                  if (node instanceof HBox) {
                        HBox equationBox = (HBox) node;
                        Label idLabel = (Label) equationBox.getChildren().get(0); // 获取算式ID标签

                        int id = Integer.parseInt(idLabel.getText());
                        if (id >= startID && id <= endID) {
                            flowPane.getChildren().remove(equationBox);
                        }
                  }
                }
               
                showAlert("算术式删除成功!");
            }
            return null;
      });

      dialog.showAndWait();
    }
});

需要添加一个新的方法deleteEquationsByRange()来实现根据ID范围删除算术式的功能:

private void deleteEquationsByRange(int startID, int endID) {
    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");

      String sql = "DELETE FROM equationtable WHERE id >= ? AND id <= ?";
      pstmt = conn.prepareStatement(sql);
      pstmt.setInt(1, startID);
      pstmt.setInt(2, endID);
      pstmt.executeUpdate();
    } 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!");
}

最后,记得在deleteMenu中添加deleteMenuItem2:

deleteMenu.getItems().addAll(deleteMenuItem,deleteMenuItem1,deleteMenuItem2);

这样就完成了根据ID范围删除算术式的功能。希望对你有帮助!

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

zqy173590939 发表于 2023-12-31 22:00:29

@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.image.Image;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Pair;

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

public class HelloApplication extends Application
{
    // 定义全局变量
    //定义一个TextArea控件作为全局变量
    TextArea infoTextArea = new TextArea();

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

    FlowPane flowPane = new FlowPane();
    ScrollPane scrollPane = new ScrollPane();// 创建一个滚动面板对象
    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) {
                generateEquation();
            }
      });

      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();
            }
      });

      MenuItem deleteMenuItem = new MenuItem("Delete by serial number");

      // Delete by serial number按钮的点击事件监听器,部分删除算数式
      deleteMenuItem.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                deleteEquations();
            }
      });

      MenuItem deleteMenuItem1 = new MenuItem("Delete all");

      // Delete all按钮的点击事件监听器,全部删除
      deleteMenuItem1.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // 删除数据库中的所有算术式
                deleteAllEquations();

                // 清空界面上的所有算术式
                flowPane.getChildren().clear();

                showAlert("所有算术式删除成功!");
            }
      });

      MenuItem mistakesEquationsCollection = new MenuItem("Redo Mistakes Equations");

      Menu fileMenu = new Menu("File");
      Menu saveMenu = new Menu("SaveEquation");
      Menu readMenu = new Menu("ReadEquation");
      Menu checkMenu = new Menu("CheckEquation");
      Menu deleteMenu = new Menu("Delete");
      Menu mistakesEquationsCollectionMenu = new Menu("MistakesEquationsCollection");

      fileMenu.getItems().addAll(generateMenuItem);
      saveMenu.getItems().add(saveMenuItem);
      readMenu.getItems().add(readMenuItem);
      checkMenu.getItems().add(checkMenuItem);
      deleteMenu.getItems().addAll(deleteMenuItem,deleteMenuItem1);
      mistakesEquationsCollectionMenu.getItems().add(mistakesEquationsCollection);

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

      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);

      //为了解决题目生成或多flowpane没有拖动条无法显示的问题
      // 将FlowPane放在一个ScrollPane中
      scrollPane.setContent(flowPane);// 设置滚动面板的内容为 flowPane,即将 flowPane 放入滚动面板中
      scrollPane.setFitToHeight(true);// 可以让滚动面板的高度自适应内容的高度
      borderPane.setCenter(scrollPane); // 将ScrollPane放置在中心位置

      HBox bottomBox = new HBox(10, viewAccuracyButton);
      HBox.setMargin(viewAccuracyButton, new Insets(50, 0, 20, 140));
      borderPane.setBottom(bottomBox);

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

      infoTextArea.setPrefSize(400, 110);
      //将TextArea控件其设置为只读
      infoTextArea.setEditable(false);

      HBox showbottomBox = new HBox(140, viewAccuracyButton, infoTextArea);
      HBox.setMargin(infoTextArea, new Insets(20, 0, 20, 0));
      borderPane.setBottom(showbottomBox);


    }


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

    //为了使generate的事件处理器更美观特意拉出了这个类
    public EquationCollection generateEquation() {
      // 创建一个警示对话框
      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();
      }
      return null;
    }

    // 生成算式的方法
    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++;
                  }
                }
            }
      }

      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) + "%");
    }

    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();
    }

    //为了使事件处理器的代码更简洁,刻意独立出了这个方法,没有具体意义
    private void deleteEquations() {
      // 读取数据库中所有题目展示到界面中
      flowPane.getChildren().clear();
      displayAllEquationsFromDatabase();

      // 创建一个警示对话框
      Dialog<Pair<String, String>> dialog = new Dialog<>();
      dialog.setTitle("删除算术式范围");
      dialog.setHeaderText(null);

      // 设置对话框的按钮
      ButtonType deleteButtonType = new ButtonType("删除", ButtonBar.ButtonData.OK_DONE);
      dialog.getDialogPane().getButtonTypes().addAll(deleteButtonType, ButtonType.CANCEL);

      // 创建并设置对话框的内容
      GridPane grid = new GridPane();
      grid.setHgap(10);
      grid.setVgap(10);
      grid.setPadding(new Insets(20, 150, 10, 10));

      TextField startIDTextField = new TextField();
      TextField endIDTextField = new TextField();

      grid.add(new Label("起始ID:"), 0, 0);
      grid.add(startIDTextField, 1, 0);
      grid.add(new Label("结束ID:"), 2, 0);
      grid.add(endIDTextField, 3, 0);

      dialog.getDialogPane().setContent(grid);

      // 点击删除按钮时的逻辑
      dialog.setResultConverter(dialogButton -> {
            if (dialogButton == deleteButtonType) {
                int startID = Integer.parseInt(startIDTextField.getText());
                int endID = Integer.parseInt(endIDTextField.getText());

                // 删除数据库中匹配的算术式
                deleteEquationsByRange(startID, endID);

                // 清空界面上的匹配的算术式
                for (Node node : flowPane.getChildren()) {
                  if (node instanceof HBox) {
                        HBox equationBox = (HBox) node;
                        Label idLabel = (Label) equationBox.getChildren().get(0); // 获取算式ID标签

                        int id = Integer.parseInt(idLabel.getText());
                        if (id >= startID && id <= endID) {
                            flowPane.getChildren().remove(equationBox);
                        }
                  }
                }

                showAlert("算术式删除成功!");
            }
            return null;
      });

      dialog.showAndWait();
    }

    private void deleteEquationsByRange(int startID, int endID) {
      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");

            String sql = "DELETE FROM equationtable WHERE id >= ? AND id <= ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, startID);
            pstmt.setInt(2, endID);
            pstmt.executeUpdate();
      } 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 void deleteAllEquations() {
      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();

            String sql = "DELETE FROM equationtable";
            stmt.executeUpdate(sql);
      } 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!");
    }



}
现在数据库中新增了一个错题集表mistakesequationtable,表的结构跟equationtable完全一样,现在需要增加错题集功能,已经创建了错题集菜单栏和重做错题按钮,现在为Redo Mistakes Equations添加事件处理器。
要求修改checkequation的逻辑,使其链接数据库,点击check后,被判定为错题的题目直接保存在错题集表mistakesequationtable中,并且获取mistakesequationtable表中ID最大值,如果表中为空则从1开始编号,如果错题集中有数据则从获取的最大值+1开始标号。获取ID最大值可以参考已存在的方法。
点击Redo Mistakes Equations后,弹出警示对话框,提示用户输入本次想要重做多少道错题,确认后则从错题集中随机抽取出相应的数目显示在界面中,要求这部分区别于读取习题,错误的题目用户可以重做,要有输入框,重做后也可检查对错和查看正确率。
给出需要添加或修改的部分。
页: 1 2 3 [4] 5
查看完整版本: Java实验完成