鱼C论坛

 找回密码
 立即注册
查看: 572|回复: 57

[学习笔记] 专用

[复制链接]
发表于 2023-12-31 23:19:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
专用
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-12-31 23:19:35 | 显示全部楼层
嗨!看来你遇到了问题,我会尽力帮助你解答。请告诉我你在编程方面遇到的问题,我会尽力给出通俗易懂且幽默的解答。不过还是需要你提供具体的问题,这样我才能帮到你。所以,请问你在编程中遇到了什么困难呢?

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-31 23:20:17 | 显示全部楼层
@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[0]);
        int operand2 = Integer.parseInt(parts[2]);
        String operator = parts[1];

        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[0]);
    }

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

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

    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完全一样,表中有
Operand1
Operator
Operand2
Result
ID
数据结构分别为:
int
char
int
int
int
,现在需要增加错题集功能,已经创建了错题集菜单栏和重做错题按钮,现在为Redo Mistakes Equations添加事件处理器。点击Redo Mistakes Equations后,弹出警示对话框,提示用户输入本次想要重做多少道错题,确认后则从错题集中随机抽取出相应的数目显示在界面中,要求这部分区别于读取习题,错误的题目用户可以重做,重做的题目展示时要有textfield,重做后也可检查对错和查看正确率。
要求修改checkequation的逻辑,使其链接数据库,点击check后,被判定为错题的题目直接保存在错题集表mistakesequationtable中,错题集表mistakesequationtable表的ID列已被我设置为自增,顺序存入即可。
给出需要添加或修改的部分的代码。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-12-31 23:20:31 | 显示全部楼层
zqy173590939 发表于 2023-12-31 23:20
@FishC
package com.example.javafxmw;

import ga ...


这段代码是一个JavaFX的应用程序,主要是用于生成和保存算术题目,并提供一些功能如查看正确率、删除题目等。

首先,我们来看看程序的整体结构。程序的入口点是main()方法,通过调用launch()方法启动JavaFX应用程序。启动后,会创建一个Stage(舞台)对象,并将stage传递给start()方法。在start()方法中,我们创建了一个菜单栏和一个FlowPane布局容器。菜单栏包含了一系列菜单项,用于生成、保存、读取和检查题目,以及删除全部或部分题目。FlowPane用于展示生成的题目。最后,我们创建了一个场景并将其设置为舞台的场景,然后显示舞台。

现在,让我们来具体了解每个功能的实现。

1. generateEquation()方法用于生成算术题目,并将题目展示在GUI界面中。它首先弹出一个对话框让用户输入题目数量,然后调用generateEquations()方法生成具体的题目,并将题目显示在GUI界面中。同时,它还连接到数据库,以便在保存题目时使用。

2. generateEquations()方法用于生成具体的算术题目。它接受一个整数参数n,表示题目数量,然后使用EquationCheckerOfRange类限定题目的范围(0到100),并生成n个题目。最后,它将题目存放在EquationCollection对象中并返回。

3. connectDatabase()方法用于连接到数据库。它使用JDBC驱动程序连接到名为"rjgzdatabase"的数据库,并获取一些数据库元数据信息。

4. saveEquations()方法用于保存题目到数据库。它首先连接到数据库,然后遍历GUI界面上的所有题目,并将题目的各个部分(操作数1、运算符、操作数2和结果)插入到equationtable表中。

5. calculateResult()方法用于计算给定算术题目的结果。它首先将算术题目字符串分割为操作数1、运算符和操作数2,然后根据运算符计算结果,并返回结果。

6. deleteEquationsByRange()方法用于根据给定范围删除数据库中的算术题目。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-1 13:17:20 | 显示全部楼层
@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.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Pair;

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

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;

    // 定义一个缓存用于保存被判定为错题的题目
    private Set<String> mistakesSet = new HashSet<>();

    @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("Normal 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) {
                // 清空之前的错题缓存
                mistakesSet.clear();

                // 检查习题并记录错题到缓存中
                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 saveMistakesEquationsMenuItem = new MenuItem("Save Mistakes Equations");

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

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

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

        Menu fileMenu = new Menu("File");
        Menu saveMenu = new Menu("Save Equation");
        Menu readMenu = new Menu("Read Equation");
        Menu checkMenu = new Menu("Check Equation");
        Menu deleteMenu = new Menu("Delete");
        Menu mistakesEquationsCollectionMenu = new Menu("Mistakes Equations Collection");

        fileMenu.getItems().addAll(generateMenuItem);
        saveMenu.getItems().addAll(saveMenuItem,saveMistakesEquationsMenuItem);
        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().addAll(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[0]);
        int operand2 = Integer.parseInt(parts[2]);
        String operator = parts[1];

        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[0]);
    }

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

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

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

                        // 将判定为错题的题目记录到缓存中
                        mistakesSet.add(equation); // 将错误的题目加入错题集缓存
                    }
                }
            }
        }

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

    // 保存错题到错题集表的方法
    private void saveMistakesEquationsToDatabase() {
        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 (String equation : mistakesSet) {
                String[] parts = equation.split(" ");
                int operand1 = Integer.parseInt(parts[0]);
                String operator = parts[1];
                int operand2 = Integer.parseInt(parts[2]);
                int result = calculateResult(equation);

                String sql = "INSERT INTO mistakesequationtable (Operand1, Operator, Operand2, Result) VALUES (?, ?, ?, ?)";
                pstmt = conn.prepareStatement(sql);
                pstmt.setInt(1, operand1);
                pstmt.setString(2, operator);
                pstmt.setInt(3, operand2);
                pstmt.setInt(4, result);
                pstmt.executeUpdate();
            }

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

    // 添加redoMistakesEquations方法实现重新做错题的功能
    private void redoMistakesEquations() {
        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());

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

            // 查询数据库中的错题数量
            int totalMistakes = getMistakesCountFromDatabase();

            if (n > totalMistakes) {
                showAlert("错题集中没有那么多错题,继续加油!");
            } else {
                // 从mistakesequationtable中随机抽出n道错题显示到界面中
                displayRandomMistakesEquations(n);
            }
        }
    }

    private int getMistakesCountFromDatabase() {
        Connection conn = null;
        Statement stmt = null;
        int totalMistakes = 0;
        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();

            // 查询mistakesequationtable中的记录总数
            ResultSet countResult = stmt.executeQuery("SELECT COUNT(*) FROM mistakesequationtable");
            countResult.next();
            totalMistakes = countResult.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!");

        return totalMistakes;
    }

    private void displayRandomMistakesEquations(int n) {
        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();

            // 查询mistakesequationtable中的记录总数
            ResultSet countResult = stmt.executeQuery("SELECT COUNT(*) FROM mistakesequationtable");
            countResult.next();
            int totalCount = countResult.getInt(1);

            // 随机抽取n道错题的ID
            Set<Integer> selectedIDs = new HashSet<>();
            Random random = new Random();
            while (selectedIDs.size() < n) {
                int randomID = random.nextInt(totalCount) + 1;
                selectedIDs.add(randomID);
            }

            // 查询并显示随机抽取的错题
            for (int id : selectedIDs) {
                ResultSet rs = stmt.executeQuery("SELECT * FROM mistakesequationtable WHERE ID = " + id);
                if (rs.next()) {
                    String equation = rs.getInt("Operand1") + " " + rs.getString("Operator") + " " +
                            rs.getInt("Operand2") + " = ?";
                    Label equationLabel = new Label(equation);
                    TextField answerField = new TextField(); // 创建一个新的文本框
                    HBox equationBox = new HBox(10, equationLabel, answerField); // 将错题和文本框放入水平布局
                    flowPane.getChildren().add(equationBox); // 将水平布局添加到 flowPane 中
                }
            }
        } 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!");
    }

}
修改代码,使得查看正确率和检查功能也支持统计错题表中的错题。
给出需要添加或修改的部分的代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-1 13:17:32 | 显示全部楼层
zqy173590939 发表于 2024-01-01 13:17
@FishC
package com.example.javafxmw;

import ga ...


为了实现查看正确率和检查功能支持统计错题表中的错题,我们需要对代码进行如下修改:

1. 在类的开头添加以下变量:
```java
private Set

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-1 13:41:33 | 显示全部楼层
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.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Pair;

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

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;

    // 定义一个缓存用于保存被判定为错题的题目
    private Set<String> mistakesSet = new HashSet<>();

    @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("Normal 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) {
                // 清空之前的错题缓存
                mistakesSet.clear();

                // 检查习题并记录错题到缓存中
                checkEquations();
            }
        });

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

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

        

        MenuItem saveMistakesEquationsMenuItem = new MenuItem("Save Mistakes Equations");

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

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

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

        Menu fileMenu = new Menu("File");
        Menu saveMenu = new Menu("Save Equation");
        Menu readMenu = new Menu("Read Equation");
        Menu checkMenu = new Menu("Check Equation");
        Menu deleteMenu = new Menu("Delete");
        Menu mistakesEquationsCollectionMenu = new Menu("Mistakes Equations Collection");

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

        MenuBar menuBar = new MenuBar();
        menuBar.getMenus().addAll(fileMenu);
        menuBar.getMenus().addAll(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[0]);
        int operand2 = Integer.parseInt(parts[2]);
        String operator = parts[1];

        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[0]);
    }

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

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

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

                        // 将判定为错题的题目记录到缓存中
                        mistakesSet.add(equation); // 将错误的题目加入错题集缓存
                    }
                }
            }
        }

        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 saveMistakesEquationsToDatabase() {
        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 (String equation : mistakesSet) {
                String[] parts = equation.split(" ");
                int operand1 = Integer.parseInt(parts[0]);
                String operator = parts[1];
                int operand2 = Integer.parseInt(parts[2]);
                int result = calculateResult(equation);

                String sql = "INSERT INTO mistakesequationtable (Operand1, Operator, Operand2, Result) VALUES (?, ?, ?, ?)";
                pstmt = conn.prepareStatement(sql);
                pstmt.setInt(1, operand1);
                pstmt.setString(2, operator);
                pstmt.setInt(3, operand2);
                pstmt.setInt(4, result);
                pstmt.executeUpdate();
            }

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

    // 添加redoMistakesEquations方法实现重新做错题的功能
    private void redoMistakesEquations() {
        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());

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

            // 查询数据库中的错题数量
            int totalMistakes = getMistakesCountFromDatabase();

            if (n > totalMistakes) {
                showAlert("错题集中没有那么多错题,继续加油!");
            } else {
                // 从mistakesequationtable中随机抽出n道错题显示到界面中
                displayRandomMistakesEquations(n);
            }
        }
    }

    private int getMistakesCountFromDatabase() {
        Connection conn = null;
        Statement stmt = null;
        int totalMistakes = 0;
        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();

            // 查询mistakesequationtable中的记录总数
            ResultSet countResult = stmt.executeQuery("SELECT COUNT(*) FROM mistakesequationtable");
            countResult.next();
            totalMistakes = countResult.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!");

        return totalMistakes;
    }

    private void displayRandomMistakesEquations(int n) {
        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();

            // 查询mistakesequationtable中的记录总数
            ResultSet countResult = stmt.executeQuery("SELECT COUNT(*) FROM mistakesequationtable");
            countResult.next();
            int totalCount = countResult.getInt(1);

            // 随机抽取n道错题的ID
            Set<Integer> selectedIDs = new HashSet<>();
            Random random = new Random();
            while (selectedIDs.size() < n) {
                int randomID = random.nextInt(totalCount) + 1;
                selectedIDs.add(randomID);
            }

            // 查询并显示随机抽取的错题
            for (int id : selectedIDs) {
                ResultSet rs = stmt.executeQuery("SELECT * FROM mistakesequationtable WHERE ID = " + id);
                if (rs.next()) {
                    String equation = rs.getInt("Operand1") + " " + rs.getString("Operator") + " " +
                            rs.getInt("Operand2") + " = ?";
                    Label equationLabel = new Label(equation);
                    TextField answerField = new TextField(); // 创建一个新的文本框
                    HBox equationBox = new HBox(10, equationLabel, answerField); // 将错题和文本框放入水平布局
                    flowPane.getChildren().add(equationBox); // 将水平布局添加到 flowPane 中
                }
            }
        } 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!");
    }

}
修改代码,使得重做错题后,也可以使用查看正确率和检查功能,点击check检查重做的错题的对错和点击viewaccuracy查看重做的题目的正确率
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-1 13:41:44 | 显示全部楼层
zqy173590939 发表于 2024-01-01 13:41
package com.example.javafxmw;

import gaijin3.*; ...


您好!根据您的需求,我稍作修改代码,使得重做错题后可以使用查看正确率和检查功能。具体修改如下:

1. 首先,在generate

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-4 11:03:34 | 显示全部楼层
@FishC
package com.example.javafxmw;

import DatabaseOperations.*;
import TeacherPostsSystem.*;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.sql.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Optional;

public class HelloApplication  extends Application{
    //初始界面的账号输入框
    public TextField accountField = new TextField("abc");

    //初始界面的密码输入框
    public PasswordField passwordField = new PasswordField();

    //创建单选选项
    ToggleGroup toggleGroup = new ToggleGroup();

    //选项,管理员登录
    RadioButton adminRadioButton = new RadioButton("管理员");

    //基础界面使用borderPane布局
    BorderPane borderPane = new BorderPane();
    //存放输入框

    //执行和数据库相关的方法所用
    DatabaseConnect connect = new DatabaseConnect();

    // 创建菜单栏
    MenuBar menuBar = new MenuBar();

    @Override
    public void start(Stage stage) {

        VBox vBox = new VBox();
        vBox.setSpacing(10);

        // 创建账号输入框
        HBox accountBox = new HBox();
        Label accountLabel = new Label("账号:");
        accountBox.getChildren().addAll(accountLabel, accountField);

        // 创建密码输入框
        HBox passwordBox = new HBox();
        Label passwordLabel = new Label("密码:");
        passwordBox.getChildren().addAll(passwordLabel, passwordField);

        // 创建登录按钮
        Button loginButton = new Button("登录");
        loginButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                // 登录功能
                login();
            }
        });

        // 创建注册按钮
        Button registerButton = new Button("注册");
        registerButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                // 注册功能,管理员账号写死,不可注册和修改,教师账号可注册
                register();
            }
        });


        // 创建单选按钮

        adminRadioButton.setToggleGroup(toggleGroup);
        adminRadioButton.setSelected(true); // 默认选中管理员登录

        RadioButton teacherRadioButton = new RadioButton("教师");
        teacherRadioButton.setToggleGroup(toggleGroup);

        // 将登录按钮和注册按钮添加到水平布局中
        HBox buttonsBox = new HBox();
        buttonsBox.getChildren().addAll(loginButton, registerButton);
        buttonsBox.setSpacing(130);

        // 将单选按钮添加到水平布局中
        HBox radioButtonsBox = new HBox();
        radioButtonsBox.getChildren().addAll(adminRadioButton, teacherRadioButton);
        radioButtonsBox.setSpacing(100);

        // 将控件添加到布局中
        vBox.getChildren().addAll(accountBox, passwordBox, buttonsBox, radioButtonsBox);
        BorderPane.setMargin(vBox, new Insets(180, 250, 180, 250));

        // 设置vBox居中显示
        borderPane.setAlignment(vBox, Pos.CENTER);
        borderPane.setCenter(vBox);

        Scene scene = new Scene(borderPane, 800, 640);
        stage.setTitle("教师岗位管理系统");
        stage.setScene(scene);
        stage.show();
    }

    //登录方法
    public void login() {

        // 清空之前的界面内容,为了第二次返回调用登录时,先清空一次界面
        borderPane.getChildren().clear();

        // 判断用户是否选中了单选按钮
        if (toggleGroup.getSelectedToggle() == null) {
            Alert alert = new Alert(Alert.AlertType.WARNING);
            alert.setTitle("提示");
            alert.setHeaderText(null);
            alert.setContentText("请选择用户类型!");
            alert.showAndWait();
            return;
        }

        // 获取用户输入的账号和密码
        String account = accountField.getText().trim();
        String password = passwordField.getText().trim();


        // 判断选择的身份
        boolean isAdmin = toggleGroup.getSelectedToggle().equals(adminRadioButton);
        String tableName = isAdmin ? "admin" : "teacher";

        // 从对应的表中查询账号和密码
        String sql = "SELECT * FROM " + tableName + " WHERE account = ?";
        try (Connection conn = connect.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            stmt.setString(1, account);
            ResultSet rs = stmt.executeQuery();
            if (rs.next()) {
                String dbPassword = rs.getString("password");
                // 对用户输入的密码进行加密,比对数据库中的密码是否一致
                if (password.equals(dbPassword)) {
                    // 登录成功,弹出提示框
                    Alert alert = new Alert(Alert.AlertType.INFORMATION);
                    alert.setTitle("提示");
                    alert.setHeaderText(null);
                    alert.setContentText("登录成功!");
                    alert.showAndWait();

                    // 展示新的界面
                    if(isAdmin) {
                        showMainScene();
                    }else {
                        showTeacherScene();
                    }
                } else {
                    // 密码错误,弹出提示框
                    Alert alert = new Alert(Alert.AlertType.ERROR);
                    alert.setTitle("错误");
                    alert.setHeaderText(null);
                    alert.setContentText("用户名或密码错误!");
                    alert.showAndWait();
                }
            } else {
                // 账号不存在,弹出提示框
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setTitle("错误");
                alert.setHeaderText(null);
                alert.setContentText("用户名或密码错误!");
                alert.showAndWait();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void showTeacherScene() {
        // 清空之前的界面内容
        borderPane.getChildren().clear();

        try (Connection conn = connect.getConnection();
             Statement stmt = conn.createStatement()) {

            // 从teacher表和teacherinfomation表中联合查询教师信息
            String sql = "SELECT t.id, t.account, t.password, ti.name, ti.gender, ti.age, ti.position, ti.worktime, ti.college " +
                    "FROM teacher t JOIN teacherinformation ti ON t.workid = ti.workid";
            ResultSet rs = stmt.executeQuery(sql);

            // 获取列数,将获取到的列放到结果集中
            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();

            // 创建表格
            TableView<ObservableList<String>> table = new TableView<>();

            // 添加表头,根据获取到的列,添加表头
            for (int i = 1; i <= columnCount; i++) {
                String columnName = metaData.getColumnName(i);
            /*
            ObservableList<String> 是每一行数据的类型,表示一行数据是一个字符串列表。
            String 是单元格中数据的类型,表示每个单元格中的数据是字符串类型。
            */
                TableColumn<ObservableList<String>, String> column = new TableColumn<>(columnName);
                // 设置表头内容居中,并设置内容只读
                column.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue().get(table.getColumns().indexOf(column))));
                table.getColumns().add(column);
            }

            // 添加数据行
            while (rs.next()) {
                ObservableList<String> data = FXCollections.observableArrayList();
                for (int i = 1; i <= columnCount; i++) {
                    String cellValue = rs.getString(i);
                    data.add(cellValue);
                }
                table.getItems().add(data);
            }

            // 创建ScrollPane并将表格放入其中
            ScrollPane scrollPane = new ScrollPane();
            scrollPane.setContent(table);
            scrollPane.setFitToHeight(true);
            scrollPane.setFitToWidth(true);

            // 将ScrollPane添加到BorderPane的中央
            borderPane.setCenter(scrollPane);
            // 创建按钮组
            HBox buttonBox = new HBox(10);
            buttonBox.setAlignment(Pos.CENTER);

            Button changePassWordButton = new Button("修改密码");
            //给按钮添加点击事件
            changePassWordButton.setOnAction(actionEvent -> changePassWord());


        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void changePassWord() {

    }


    public void showMainScene() {
        // 清空之前的界面内容
        borderPane.getChildren().clear();

        // 创建菜单
        Menu fileMenu = new Menu("File");
        Menu addMenu = new Menu("Add");
        Menu deleteMenu = new Menu("Delete");
        Menu editMenu = new Menu("Edit");
        Menu searchMenu = new Menu("Search");
        Menu setMenu = new Menu("Settings");

        // 创建菜单项
        MenuItem addTeacherItem = new MenuItem("Add Teacher");
        MenuItem editTeacherItem = new MenuItem("Edit Teacher");
        MenuItem deleteTeacherItem = new MenuItem("Delete Teacher");
        MenuItem searchTeacherItem = new MenuItem("Search Teacher");
        MenuItem logoutItem = new MenuItem("Log Out");

        // 为菜单项添加事件处理程序
        addTeacherItem.setOnAction(e -> addTeacher());
        editTeacherItem.setOnAction(e -> amend());
        deleteTeacherItem.setOnAction(e -> deleteTeacher());
        searchTeacherItem.setOnAction(e -> searchTeacher());
        logoutItem.setOnAction(e -> logout());

        // 将菜单项添加到菜单中
        fileMenu.getItems().addAll(setMenu);
        addMenu.getItems().addAll(addTeacherItem);
        deleteMenu.getItems().addAll(deleteTeacherItem);
        editMenu.getItems().addAll(editTeacherItem);
        searchMenu.getItems().addAll(searchTeacherItem);
        setMenu.getItems().addAll(logoutItem);


        // 将菜单添加到菜单栏
        menuBar.getMenus().add(fileMenu);
        menuBar.getMenus().add(addMenu);
        menuBar.getMenus().add(deleteMenu);
        menuBar.getMenus().add(editMenu);
        menuBar.getMenus().add(searchMenu);

        // 将菜单栏添加到布局中
        borderPane.setTop(menuBar);




        try (Connection conn = connect.getConnection();
             Statement stmt = conn.createStatement()) {

            // 从teacher表中查询教师信息
            String sql = "SELECT * FROM teacherinformation";
            ResultSet rs = stmt.executeQuery(sql);

            // 获取列数,将获取到的列放到结果集中
            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();

            // 创建表格
            TableView<ObservableList<String>> table = new TableView<>();

            // 添加表头,根据获取到的列,添加表头
            for (int i = 1; i <= columnCount; i++) {
                String columnName = metaData.getColumnName(i);
            /*
            ObservableList<String> 是每一行数据的类型,表示一行数据是一个字符串列表。
            String 是单元格中数据的类型,表示每个单元格中的数据是字符串类型。
            */
                TableColumn<ObservableList<String>, String> column = new TableColumn<>(columnName);
                // 设置表头内容居中,并设置内容只读
                column.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue().get(table.getColumns().indexOf(column))));
                table.getColumns().add(column);
            }

            // 添加数据行
            while (rs.next()) {
                ObservableList<String> data = FXCollections.observableArrayList();
                for (int i = 1; i <= columnCount; i++) {
                    String cellValue = rs.getString(i);
                    data.add(cellValue);
                }
                table.getItems().add(data);
            }

            // 创建ScrollPane并将表格放入其中
            ScrollPane scrollPane = new ScrollPane();
            scrollPane.setContent(table);
            scrollPane.setFitToHeight(true);
            scrollPane.setFitToWidth(true);


            // 添加ScrollPane到布局中
            borderPane.setCenter(scrollPane);

            // 创建按钮组
            HBox buttonBox = new HBox(10);
            buttonBox.setAlignment(Pos.CENTER);

            // 添加按钮
            Button addButton = new Button("添加");
            addButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent actionEvent) {
                    // 调用添加教师的方法
                    addTeacher();
                }
            });

            // 修改按钮
            Button editButton = new Button("修改");
            editButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent actionEvent) {
                    amend();
                }
            });

            // 删除按钮
            Button deleteButton = new Button("删除");
            deleteButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent actionEvent) {
                    // 调用删除教师的方法
                    deleteTeacher();
                }
            });

            // 查询按钮
            Button searchButton = new Button("查询");
            searchButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent actionEvent) {
                    // 调用查询教师的方法
                    searchTeacher();
                }
            });

            // 将按钮添加到按钮组中
            buttonBox.getChildren().addAll(addButton, editButton, deleteButton, searchButton);

            // 添加按钮组到布局底部
            borderPane.setBottom(buttonBox);

        } catch (SQLException e) {
            e.printStackTrace();
            // 异常处理
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setTitle("错误");
            alert.setHeaderText(null);
            alert.setContentText("显示教师信息失败!");
            alert.showAndWait();
        }
    }

    private void logout() {
        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setTitle("确认退出");
        alert.setHeaderText(null);
        alert.setContentText("确定要退出登录吗?");

        Optional<ButtonType> result = alert.showAndWait();
        if (result.isPresent() && result.get() == ButtonType.OK) {
            // 用户点击了确定按钮,执行退出登录操作
            Stage stage = new Stage();
            start(stage);
        }
    }



    private void searchTeacher() {
        // 调用创建对话框的方法,并让用户输入要查询的教师工号
        Optional<ArrayList<TextField>> result = createInputDialog("查询", "请输入要查询的教师工号");

        if (result.isPresent()) {
            // 用户点击了 "确定" 按钮,获取输入的工号
            ArrayList<TextField> idField = result.get();
            String workId = idField.get(0).getText();


            // 根据工号从数据库中查询对应的教师信息
            TeacherInformation teacher = queryById(workId);

            if (teacher == null) {
                // 如果没有查询到对应的教师信息,提示用户并返回
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setTitle("错误");
                alert.setHeaderText("未找到对应的教师信息");
                alert.setContentText("请检查输入的工号是否正确!");
                alert.showAndWait();
            } else {
                // 创建一个新的对话框,显示查询到的教师信息
                Dialog<String> infoDialog = new Dialog<>();
                infoDialog.setTitle("查询结果");
                infoDialog.setHeaderText(null);

                // 创建文本区域显示教师信息
                TextArea textArea = new TextArea();
                textArea.setEditable(false);
                textArea.appendText("姓名: " + teacher.getName() + "\n");
                textArea.appendText("性别: " + teacher.getGender() + "\n");
                textArea.appendText("年龄: " + teacher.getAge() + "\n");
                textArea.appendText("工号: " + teacher.getWorkid() + "\n");
                textArea.appendText("职称: " + teacher.getPosition() + "\n");
                textArea.appendText("工作时间: " + teacher.getWorktime() + "\n");

                // 将文本区域添加到对话框中
                infoDialog.getDialogPane().setContent(textArea);

                // 添加 "确定" 按钮
                infoDialog.getDialogPane().getButtonTypes().add(ButtonType.OK);

                // 显示对话框并等待用户响应
                infoDialog.showAndWait();
            }
        }
    }

    //删除教师
    private void deleteTeacher() {
        // 调用创建对话框的方法,并让用户输入要删除的教师工号
        Optional<ArrayList<TextField>> result = createInputDialog("删除", "请输入要删除的教师工号");

        if (result.isPresent()) {
            // 用户点击了 "确定" 按钮,获取输入的工号
            ArrayList<TextField> idField = result.get();
            String workId = idField.get(0).getText();


            // 根据工号从数据库中查询对应的教师信息
            TeacherInformation teacher = queryById(workId);

            if (teacher == null) {
                // 如果没有查询到对应的教师信息,提示用户并返回
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setTitle("错误");
                alert.setHeaderText("未找到对应的教师信息");
                alert.setContentText("请检查输入的工号是否正确!");
                alert.showAndWait();
            } else {
                // 执行删除操作
                if (connect.deleteTeacherById(workId)) {
                    // 删除成功,提示用户
                    Alert successAlert = new Alert(Alert.AlertType.INFORMATION);
                    successAlert.setTitle("删除成功");
                    successAlert.setHeaderText(null);
                    successAlert.setContentText("教师信息删除成功!");
                    successAlert.showAndWait();

                    // 刷新界面
                    showMainScene();
                } else {
                    // 删除失败,提示用户
                    Alert errorAlert = new Alert(Alert.AlertType.ERROR);
                    errorAlert.setTitle("删除失败");
                    errorAlert.setHeaderText(null);
                    errorAlert.setContentText("教师信息删除失败!");
                    errorAlert.showAndWait();
                }
            }
        }
    }



    private void addTeacher() {

        // 创建一个对话框窗口
        Dialog<ArrayList<TextField>> dialog = new Dialog<>();
        dialog.setTitle("添加教师");
        dialog.setHeaderText(null);

        // 设置对话框的按钮
        ButtonType addButton = new ButtonType("添加", ButtonBar.ButtonData.OK_DONE);
        ButtonType cancelButton = new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE);
        dialog.getDialogPane().getButtonTypes().addAll(addButton, cancelButton);

        // 创建表单布局
        GridPane formGrid = new GridPane();
        formGrid.setHgap(10);
        formGrid.setVgap(10);
        formGrid.setPadding(new Insets(20));

        // 创建表单字段和标签
        ArrayList<TextField> fields = new ArrayList<>();
        ArrayList<String> labels = new ArrayList<>(Arrays.asList("姓名:", "性别:", "年龄:", "工号:", "职位:", "所属学院:", "工作时间:"));
        for (int i = 0; i < labels.size(); i++) {
            TextField field = new TextField();
            Label label = new Label(labels.get(i));
            formGrid.add(label, 0, i);
            formGrid.add(field, 1, i);
            fields.add(field);
        }

        // 将表单布局设置为对话框的内容
        dialog.getDialogPane().setContent(formGrid);

        // 设置对话框的结果转换器
        dialog.setResultConverter(dialogButton -> {
            if (dialogButton == addButton) {
                // 点击添加按钮时,将输入的教师信息返回
                return fields;
            }
            return null;
        });

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

        // 处理用户操作结果
        result.ifPresent(inputs -> {
            // 获取用户输入的教师信息
            String name = inputs.get(0).getText();
            String gender = inputs.get(1).getText();
            int age = Integer.parseInt(inputs.get(2).getText());
            String workid = inputs.get(3).getText();
            String position = inputs.get(4).getText();
            String college = inputs.get(5).getText();
            String worktime = inputs.get(6).getText();

            // 将教师信息插入到数据库中
            try {
                connect.insertTeacher(name, gender, age, workid, position, college, worktime);
                // 插入成功后,刷新主界面
                showMainScene();
            } catch (SQLException e) {
                e.printStackTrace();
            }


        });
    }

    //创建对话框
    private GridPane createTeacherForm() {
        // 创建表单布局
        GridPane formGrid = new GridPane();
        formGrid.setHgap(10);
        formGrid.setVgap(10);

        // 定义表单字段和标签的名称
        ArrayList<String> fieldLabels = new ArrayList<>(Arrays.asList("姓名:", "性别:", "年龄:", "职位:", "所属学院:", "工作时间:"));
        ArrayList<TextField> fields = new ArrayList<>();

        // 使用循环创建表单字段和标签
        for (int i = 0; i < fieldLabels.size(); i++) {
            TextField field = new TextField();
            Label label = new Label(fieldLabels.get(i));
            formGrid.add(label, 0, i);
            formGrid.add(field, 1, i);
            fields.add(field);
        }

        return formGrid;
    }


    //修改教师信息
    private void amend() {
        // 调用创建对话框的方法,并让用户输入要查询的教师工号
        Optional<ArrayList<TextField>> result = createInputDialog("修改", "请输入要修改的教师工号");

        if(result.isPresent()) {
            // 用户点击了 "确定" 按钮,获取输入的工号
            ArrayList<TextField> idField = result.get();
            String workId = idField.get(0).getText();


            // 根据工号从数据库中查询对应的教师信息
            TeacherInformation teacher = queryById(workId);

            if(teacher == null) {
                // 如果没有查询到对应的教师信息,提示用户并返回
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setTitle("错误");
                alert.setHeaderText("未找到对应的教师信息");
                alert.setContentText("请检查输入的工号是否正确!");
                alert.showAndWait();
            } else {
                // 创建一个对话框窗口
                Dialog<ArrayList<TextField>> dialog1 = new Dialog<>();
                dialog1.setTitle("修改教师岗位信息");
                dialog1.setHeaderText(null);

                // 设置对话框的按钮
                ButtonType addButton = new ButtonType("修改" , ButtonBar.ButtonData.OK_DONE);
                ButtonType cancelButton = new ButtonType("取消" , ButtonBar.ButtonData.CANCEL_CLOSE);
                dialog1.getDialogPane().getButtonTypes().addAll(addButton , cancelButton);

                // 创建表单布局并获取字段对象
                GridPane formGrid = createTeacherForm();
                ArrayList<TextField> fields = new ArrayList<>(formGrid.getChildren().size());
                for(Node node : formGrid.getChildren()) {
                    if(node instanceof TextField) {
                        fields.add((TextField) node);
                    }
                }

                // 设置对话框的结果转换器
                dialog1.setResultConverter(dialogButton -> {
                    if(dialogButton == addButton) {
                        // 点击添加按钮时,将输入的教师信息返回
                        return fields;
                    }
                    return null;
                });

                // 将表单布局设置为对话框的内容
                dialog1.getDialogPane().setContent(formGrid);
                // 显示对话框并等待用户操作
                Optional<ArrayList<TextField>> result1 = dialog1.showAndWait();
                // 处理用户操作结果
                result1.ifPresent(inputs -> {
                    // 获取用户输入的教师信息
                    String name = inputs.get(0).getText();
                    String gender = inputs.get(1).getText();
                    int age = Integer.parseInt(inputs.get(2).getText());
                    String position = inputs.get(3).getText();
                    String college = inputs.get(4).getText();
                    String worktime = inputs.get(5).getText();

                    // 将教师信息插入到数据库中
                    connect.updateTeacher(name, gender, age ,workId , position, college, worktime);

                    // 刷新教师列表
                    showMainScene();
                });
            }
        }
    }

    //根据工号查询数据库中是否有对应的教师信息
    public TeacherInformation queryById(String workId) {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        TeacherInformation teacher = null;

        try {
            // 获取数据库连接
            conn = connect.getConnection();

            // 创建 PreparedStatement 对象,并设置占位符参数
            String sql = "SELECT * FROM teacherinformation WHERE workid=?";
            stmt = conn.prepareStatement(sql);
            stmt.setString(1, workId);

            // 执行查询操作
            rs = stmt.executeQuery();

            // 处理结果集,将查询到的教师信息保存到一个 Teacher 对象中
            if (rs.next()) {
                String name = rs.getString("name");
                String gender = rs.getString("gender");
                int age = rs.getInt("age");
                String position = rs.getString("position");
                String worktime = rs.getString("worktime");
                String college = rs.getString("college");
                teacher = new TeacherInformation(name, gender, age, workId, position,worktime,college);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }  finally {
            // 关闭数据库连接,语句和结果集
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return teacher;
    }

    public void register() {
        String account = accountField.getText();
        String password = passwordField.getText();

        // 检查用户名是否已存在
        if (checkNameExist(account)) {
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setTitle("错误");
            alert.setHeaderText(null);
            alert.setContentText("用户名已存在!");
            alert.showAndWait();
            return;
        }

        // 注册新用户
        if (createTeacherAccount(account, password)) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("提示");
            alert.setHeaderText(null);
            alert.setContentText("注册成功!");
            alert.showAndWait();
        } else {
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setTitle("错误");
            alert.setHeaderText(null);
            alert.setContentText("注册失败!");
            alert.showAndWait();
        }
    }


    private boolean createTeacherAccount(String account, String password) {
        String sql = "INSERT INTO teacher (account, password) VALUES (?, ?)";
        try (Connection conn = connect.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            stmt.setString(1, account);
            stmt.setString(2, password);
            int result = stmt.executeUpdate();
            return result > 0;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    private boolean checkNameExist(String name) {
        boolean result = false;
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = connect.getConnection();
            // 执行查询语句
            String sql = "SELECT account FROM teacher";
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);

            // 判断是否有和name相同的值
            while (rs.next()) {
                String account = rs.getString("account");
                if (account.equals(name)) {
                    result = true;
                    break;
                }
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 关闭数据库连接
            try {
                if (rs != null) {
                    rs.close();
                }
                if (stmt != null) {
                    stmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        return result;
    }

    //创建一个对话框
    private Optional<ArrayList<TextField>> createInputDialog(String title, String headerText) {
        Dialog<ButtonType> dialog = new Dialog<>();
        dialog.setTitle(title);
        dialog.setHeaderText(headerText);

        // 创建工号输入框并添加到对话框中
        TextField workIdField = new TextField();
        dialog.getDialogPane().setContent(workIdField);

        // 创建 "确定" 和 "取消" 按钮并添加到对话框中
        ButtonType confirmButtonType = new ButtonType("确定", ButtonBar.ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(confirmButtonType, ButtonType.CANCEL);

        // 设置按钮的可用性
        Node confirmButton = dialog.getDialogPane().lookupButton(confirmButtonType);
        confirmButton.setDisable(true);
        workIdField.textProperty().addListener((observable, oldValue, newValue) -> {
            confirmButton.setDisable(newValue.trim().isEmpty());
        });

        // 显示对话框并等待用户响应
        Optional<ButtonType> result = dialog.showAndWait();

        if (result.isPresent() && result.get() == confirmButtonType) {
            ArrayList<TextField> fields = new ArrayList<>();
            fields.add(workIdField);
            return Optional.of(fields);
        } else {
            return Optional.empty();
        }
    }

    public static void main(String[] args) {
        launch();
    }
}
修改代码,点击logout后,发生错误“你正在尝试将一个已经作为另一个场景的根节点的BorderPane设置为另一个场景的根节点,这是不允许的。你需要确保每个场景只有一个根节点,并且根节点只能属于一个场景。”在退出登录后,调用start方法前,将BorderPane从前一个场景中移除,再调用start方法
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-4 11:03:51 | 显示全部楼层
zqy173590939 发表于 2024-01-04 11:03
@FishC
package com.example.javafxmw;

import Da ...


你好!你遇到的问题是因为在退出登录后,调用start方法前,没有将前一个场景中的BorderPane从界面中移除。这就导致了你想要

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-4 11:04:30 | 显示全部楼层
FishC 发表于 2024-1-4 11:03
你好!你遇到的问题是因为在退出登录后,调用start方法前,没有将前一个场景中的BorderPane从界面中移 ...

你的回复为什么没有完全显示?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-4 11:04:40 | 显示全部楼层
zqy173590939 发表于 2024-01-04 11:04
你的回复为什么没有完全显示?


非常抱歉,我的回复似乎被截断了。让我重新回答你的问题。

你遇到的问题是因为在退出登录后,调用start方法前,没有将前一个场景中的BorderPane从界面中移除。这就导致了你想要将一个已经作为另一个场景的根节点的BorderPane设置为另一个场景的根节点时发生了错误。

要解决这个问题,我们可以在退出登录时将BorderPane从前一个场景中移除,然后再调用start方法来展示新的场景。

具体做法是,在logout方法中添加以下代码来移除BorderPane:
  1. borderPane.getChildren().clear();
复制代码


然后在showMainScene和showTeacherScene方法中也加上清空BorderPane的代码,以确保每次展示新场景时都没有之前的内容残留:
  1. borderPane.getChildren().clear();
复制代码


这样,在退出登录后调用start方法时,就能正常地展示新的场景了。希望这次回答能够解决你的问题!如果还有其他疑问,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-4 11:27:38 | 显示全部楼层
@FishC
写一份教师岗位管理系统的背景调查报告,写出开发这个系统的必要性
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-4 11:27:55 | 显示全部楼层
zqy173590939 发表于 2024-01-04 11:27
@FishC
写一份教师岗位管理系统的背景调查报告,写出 ...


教师岗位管理系统的背景调查报告

1. 引言
教师是社会中非常重要的一群人,他们肩负着培养下一代的重任。然而,在当前的教育领域,对于教师的管理和评估仍然存在一些困难和挑战。因此,我们有必要开发一种教师岗位管理系统,以提高教师管理的效率和准确性。

2. 必要性
教师岗位管理系统的开发有以下几个必要性:

2.1 提高管理效率
传统的教师管理方式使用纸质档案和表格进行记录,工作量大且容易出现错误。而一套完善的教师岗位管理系统可以集成各类教师信息,方便管理者实时查看和处理相关数据,从而提高管理效率。

2.2 优化资源分配
通过教师岗位管理系统,我们可以更好地了解教师的背景、能力和特长,以便更好地进行教师岗位分配。系统可以根据教师的专业知识和经验,自动匹配合适的岗位,从而优化资源分配。

2.3 支持绩效评估
教师绩效评估是教育系统中重要的一环,可以帮助提高教学质量和教师的发展。通过教师岗位管理系统,可以记录和分析教师的教学成果、学术研究等数据,为教师绩效评估提供支持和依据。

2.4 促进交流共享
教师岗位管理系统可以提供一个交流平台,方便教师之间的沟通和经验分享。教师可以通过系统发布教学资源、交流心得,从而促进教师团队的合作和共享。

3. 结论
教师岗位管理系统的开发对于优化教师管理、提高教学质量具有重要意义。它能够提高管理效率、优化资源分配、支持绩效评估并促进教师交流共享。因此,开发这个系统是必要且值得推进的工作。

希望这份背景调查报告能够对您有所帮助!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-5 15:11:17 | 显示全部楼层
@FishC
package com.example.javafxmw;

import DatabaseOperations.*;
import TeacherPostsSystem.*;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.sql.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Optional;

public class HelloApplication  extends Application{
    //初始界面的账号输入框
    public TextField accountField = new TextField("abc");

    //初始界面的密码输入框
    public PasswordField passwordField = new PasswordField();

    //创建单选选项
    public ToggleGroup toggleGroup = new ToggleGroup();

    //选项,管理员登录
    public RadioButton adminRadioButton = new RadioButton("管理员");
    public RadioButton teacherRadioButton = new RadioButton("教师");

    //基础界面使用borderPane布局
    private BorderPane borderPane = new BorderPane();
    //存放输入框

    //执行和数据库相关的方法所用
    public DatabaseConnect connect = new DatabaseConnect();
    // 创建菜单栏



    @Override
    public void start(Stage stage) {

        borderPane.getChildren().clear();
        VBox vBox = new VBox();
        vBox.setSpacing(10);

        // 创建账号输入框
        HBox accountBox = new HBox();
        Label accountLabel = new Label("账号:");
        accountBox.getChildren().addAll(accountLabel, accountField);

        // 创建密码输入框
        HBox passwordBox = new HBox();
        Label passwordLabel = new Label("密码:");
        passwordBox.getChildren().addAll(passwordLabel, passwordField);

        // 创建登录按钮
        Button loginButton = new Button("登录");
        loginButton.setOnAction(actionEvent -> login());

        // 创建注册按钮
        Button registerButton = new Button("注册");
        registerButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                // 获取当前选中的单选按钮
                RadioButton selectedRadioButton = (RadioButton) toggleGroup.getSelectedToggle();

                // 判断是否为教师选项
                if (selectedRadioButton == teacherRadioButton) {
                    // 执行教师注册功能
                    register();
                } else {
                    // 弹出提示框,告知不能进行管理员注册
                    Alert alert = new Alert(Alert.AlertType.ERROR);
                    alert.setTitle("错误");
                    alert.setHeaderText(null);
                    alert.setContentText("不能进行管理员注册!");
                    alert.showAndWait();
                }
            }
        });



        // 创建单选按钮

        adminRadioButton.setToggleGroup(toggleGroup);
        adminRadioButton.setSelected(true); // 默认选中管理员登录

        teacherRadioButton.setToggleGroup(toggleGroup);

        // 将登录按钮和注册按钮添加到水平布局中
        HBox buttonsBox = new HBox();
        buttonsBox.getChildren().addAll(loginButton, registerButton);
        buttonsBox.setSpacing(130);

        // 将单选按钮添加到水平布局中
        HBox radioButtonsBox = new HBox();
        radioButtonsBox.getChildren().addAll(adminRadioButton, teacherRadioButton);
        radioButtonsBox.setSpacing(100);

        // 将控件添加到布局中
        vBox.getChildren().addAll(accountBox, passwordBox, buttonsBox, radioButtonsBox);
        BorderPane.setMargin(vBox, new Insets(180, 250, 180, 250));

        // 设置vBox居中显示
        borderPane.setAlignment(vBox, Pos.CENTER);
        borderPane.setCenter(vBox);

        Scene scene = new Scene(borderPane, 800, 640);
        stage.setTitle("教师岗位管理系统");
        stage.setScene(scene);
        stage.show();
    }

    //登录方法
    public void login() {
        String currentAccountWorkId ;

        // 获取用户输入的账号和密码,并去掉空白字符
        String account = accountField.getText().trim();
        String password = passwordField.getText().trim();

        // 判断选择的身份
        boolean isAdmin = toggleGroup.getSelectedToggle().equals(adminRadioButton);
        String tableName = isAdmin ? "admin" : "teacher";

        // 从对应的表中查询账号和密码
        String sql = "SELECT * FROM " + tableName + " WHERE account = ?";
        try (Connection conn = connect.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            stmt.setString(1, account);
            ResultSet rs = stmt.executeQuery();
            if (rs.next()) {
                String dbPassword = rs.getString("password");
                // 对用户输入的密码进行加密,比对数据库中的密码是否一致
                if (password.equals(dbPassword)) {
                    // 登录成功,弹出提示框
                    Alert alert = new Alert(Alert.AlertType.INFORMATION);
                    alert.setTitle("提示");
                    alert.setHeaderText(null);
                    alert.setContentText("登录成功!");
                    alert.showAndWait();

                    // 展示新的界面
                    if(isAdmin) {

                        showAdminScene();
                    }else {
                        currentAccountWorkId = getWorkIdByAccount(account);
                        showTeacherScene(currentAccountWorkId);
                    }
                } else {
                    // 密码错误,弹出提示框
                    Alert alert = new Alert(Alert.AlertType.ERROR);
                    alert.setTitle("错误");
                    alert.setHeaderText(null);
                    alert.setContentText("用户名或密码错误!");
                    alert.showAndWait();
                }
            } else {
                // 账号不存在,弹出提示框
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setTitle("错误");
                alert.setHeaderText(null);
                alert.setContentText("用户名或密码错误!");
                alert.showAndWait();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private String getWorkIdByAccount(String account) {
        String sql = "SELECT workid FROM teacher WHERE account = ?";
        try (Connection conn = connect.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            stmt.setString(1, account);
            ResultSet rs = stmt.executeQuery();
            if (rs.next()) {
                return rs.getString("workid");
            } else {
                return null;
            }
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }
    public void showTeacherScene(String currentAccountWorkId) {
        // 清空之前的界面内容
        borderPane.getChildren().clear();

        try (Connection conn = connect.getConnection()) {
            // 从teacher表和teacherinfomation表中联合查询教师信息,获取的信息是当前账户对应workid的信息
            String sql = "SELECT t.id, t.account, t.password, ti.name, ti.gender, ti.age, ti.position, ti.worktime, ti.college "
                    + "FROM teacher t LEFT JOIN teacherinformation ti ON t.workid = ti.workid "
                    + "WHERE t.workid = ?";
            PreparedStatement stmt = conn.prepareStatement(sql);
            stmt.setString(1, currentAccountWorkId);
            ResultSet rs = stmt.executeQuery();

            // 获取列数,将获取到的列放到结果集中
            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();

            // 创建表格
            TableView<ObservableList<String>> table = new TableView<>();

            // 添加表头,根据获取到的列,添加表头
            for (int i = 1; i <= columnCount; i++) {
                String columnName = metaData.getColumnName(i);
                /*
                 * ObservableList<String> 是每一行数据的类型,表示一行数据是一个字符串列表。 String 是单元格中数据的类型,
                 * 表示每个单元格中的数据是字符串类型。
                 */
                TableColumn<ObservableList<String>, String> column = new TableColumn<>(columnName);
                // 设置表头内容居中,并设置内容只读
                column.setCellValueFactory(
                        param -> new ReadOnlyObjectWrapper<>(param.getValue().get(table.getColumns().indexOf(column))));
                table.getColumns().add(column);
            }

            // 添加数据行
            while (rs.next()) {
                ObservableList<String> data = FXCollections.observableArrayList();
                for (int i = 1; i <= columnCount; i++) {
                    String cellValue = rs.getString(i);
                    // 处理空值
                    if (cellValue == null) {
                        cellValue = "无";
                    }
                    data.add(cellValue);
                }
                table.getItems().add(data);
            }

            // 创建ScrollPane并将表格放入其中
            ScrollPane scrollPane = new ScrollPane();
            scrollPane.setContent(table);
            scrollPane.setFitToHeight(true);
            scrollPane.setFitToWidth(true);

            // 将ScrollPane添加到BorderPane的中央
            borderPane.setCenter(scrollPane);

            // 创建按钮组
            HBox buttonBox = new HBox(10);
            buttonBox.setAlignment(Pos.CENTER);

            //添加个人信息
            Button personalInfoButton = new Button("添加个人信息");
            personalInfoButton.setOnAction(actionEvent -> addPersonalInfo());

            Button changePassWordButton = new Button("修改密码");
            changePassWordButton.setOnAction(actionEvent -> changePassWord());

            buttonBox.getChildren().addAll(changePassWordButton,personalInfoButton);
            borderPane.setBottom(buttonBox);

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void addPersonalInfo() {

    }


    public void changePassWord() {
        // 调用创建对话框的方法,并让用户输入要修改密码的教师账号
        Optional<ArrayList<TextField>> result = createInputDialog("修改密码", "请输入账号");
        if (result.isPresent()) {
            ArrayList<TextField> idField = result.get();

            //获取用户输入的账号
            String enteredAccount = idField.get(0).getText();

            // 创建对话框,让用户输入工号
            TextInputDialog dialog = new TextInputDialog();
            dialog.setTitle("修改密码");
            dialog.setHeaderText(null);
            dialog.setContentText("请输入工号:");

            // 等待用户输入工号
            Optional<String> workIdResult = dialog.showAndWait();

            if (workIdResult.isPresent()) {
                // 获取用户输入的工号
                String enteredWorkId = workIdResult.get();

                // 获取数据库中的工号
                String storedWorkId = getWorkIdByAccount(enteredAccount);

                if (storedWorkId != null) {
                    if (storedWorkId.equals(enteredWorkId)) {
                        // 创建表单布局
                        GridPane formGrid = new GridPane();
                        formGrid.setHgap(10);
                        formGrid.setVgap(10);

                        // 定义表单字段和标签的名称
                        ArrayList<String> fieldLabels = new ArrayList<>(Arrays.asList("新密码", "确认新密码"));
                        ArrayList<TextField> fields = new ArrayList<>();

                        // 使用循环创建表单字段和标签
                        for (int i = 0; i < fieldLabels.size(); i++) {
                            TextField field = new TextField();
                            Label label = new Label(fieldLabels.get(i));
                            formGrid.add(label, 0, i);
                            formGrid.add(field, 1, i);
                            fields.add(field);
                        }

                        // 显示对话框,并等待用户点击按钮
                        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
                        alert.setTitle("修改密码");
                        alert.setHeaderText(null);
                        alert.getDialogPane().setContent(formGrid);
                        Optional<ButtonType> buttonResult = alert.showAndWait();

                        if (buttonResult.isPresent() && buttonResult.get() == ButtonType.OK) {
                            // 检查两次输入的密码是否一致
                            if (fields.get(0).getText().equals(fields.get(1).getText())) {
                                String newPassword = fields.get(0).getText();
                                // 调用数据库操作类的方法更新密码
                                connect.updatePassWord(enteredAccount, newPassword);
                                //刷新界面
                                showTeacherScene(enteredWorkId);
                            }
                        }
                    } else {
                        // 工号不匹配,提示错误信息
                        Alert alert = new Alert(Alert.AlertType.ERROR);
                        alert.setTitle("错误");
                        alert.setHeaderText(null);
                        alert.setContentText("输入的工号与账号不匹配!");
                        alert.showAndWait();
                    }
                } else {
                    // 账号不存在,提示错误信息
                    Alert alert = new Alert(Alert.AlertType.ERROR);
                    alert.setTitle("错误");
                    alert.setHeaderText(null);
                    alert.setContentText("输入的账号不存在!");
                    alert.showAndWait();
                }
            }
        }
    }

    //管理员界面
    public void showAdminScene() {
        // 清空之前的界面内容
        borderPane.getChildren().clear();

        try (Connection conn = connect.getConnection();
             Statement stmt = conn.createStatement()) {

            // 从teacher表中查询教师信息
            String sql = "SELECT * FROM teacherinformation";
            ResultSet rs = stmt.executeQuery(sql);

            // 获取列数,将获取到的列放到结果集中
            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();

            // 创建表格
            TableView<ObservableList<String>> table = new TableView<>();

            // 添加表头,根据获取到的列,添加表头
            for (int i = 1; i <= columnCount; i++) {
                String columnName = metaData.getColumnName(i);
            /*
            ObservableList<String> 是每一行数据的类型,表示一行数据是一个字符串列表。
            String 是单元格中数据的类型,表示每个单元格中的数据是字符串类型。
            */
                TableColumn<ObservableList<String>, String> column = new TableColumn<>(columnName);
                // 设置表头内容居中,并设置内容只读
                column.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue().get(table.getColumns().indexOf(column))));
                table.getColumns().add(column);
            }

            // 添加数据行
            while (rs.next()) {
                ObservableList<String> data = FXCollections.observableArrayList();
                for (int i = 1; i <= columnCount; i++) {
                    String cellValue = rs.getString(i);
                    data.add(cellValue);
                }
                table.getItems().add(data);
            }

            // 创建ScrollPane并将表格放入其中
            ScrollPane scrollPane = new ScrollPane();
            scrollPane.setContent(table);
            scrollPane.setFitToHeight(true);
            scrollPane.setFitToWidth(true);


            // 添加ScrollPane到布局中
            borderPane.setCenter(scrollPane);

            // 创建菜单
            Menu fileMenu = new Menu("File");
            Menu addMenu = new Menu("Add");
            Menu deleteMenu = new Menu("Delete");
            Menu editMenu = new Menu("Edit");
            Menu searchMenu = new Menu("Search");
            Menu setMenu = new Menu("Settings");

            // 创建菜单项
            MenuItem addTeacherItem = new MenuItem("Add Teacher");
            MenuItem editTeacherItem = new MenuItem("Edit Teacher");
            MenuItem deleteTeacherItem = new MenuItem("Delete Teacher");
            MenuItem searchTeacherItem = new MenuItem("Search Teacher");
            MenuItem logoutItem = new MenuItem("Log Out");

            // 为菜单项添加事件处理程序
            addTeacherItem.setOnAction(e -> addTeacher());
            editTeacherItem.setOnAction(e -> amend());
            deleteTeacherItem.setOnAction(e -> deleteTeacher());
            searchTeacherItem.setOnAction(e -> searchTeacher());
            logoutItem.setOnAction(e -> logout());

            // 将菜单项添加到菜单中
            fileMenu.getItems().addAll(setMenu);
            addMenu.getItems().addAll(addTeacherItem);
            deleteMenu.getItems().addAll(deleteTeacherItem);
            editMenu.getItems().addAll(editTeacherItem);
            searchMenu.getItems().addAll(searchTeacherItem);
            setMenu.getItems().addAll(logoutItem);

            MenuBar menuBar = new MenuBar();
            // 将菜单添加到菜单栏
            menuBar.getMenus().addAll(fileMenu, addMenu,editMenu, deleteMenu, searchMenu);

            // 将菜单栏添加到布局中
            borderPane.setTop(menuBar);

        } catch (SQLException e) {
            e.printStackTrace();
            // 异常处理
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setTitle("错误");
            alert.setHeaderText(null);
            alert.setContentText("显示教师信息失败!");
            alert.showAndWait();
        }
    }

    private void logout() {
        BorderPane borderPane = new BorderPane();

        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setTitle("确认退出");
        alert.setHeaderText(null);
        alert.setContentText("确定要退出登录吗?");

        Optional<ButtonType> result = alert.showAndWait();
        if (result.isPresent() && result.get() == ButtonType.OK) {
            // 用户点击了确定按钮,执行退出登录操作

            initializeLoginData();

            borderPane.getChildren().clear();

            Stage stage = new Stage();
            start(stage);
        }
    }

    private void initializeLoginData() {
        // 重置登录界面的数据
        accountField.clear();
        passwordField.clear();
    }

    private void searchTeacher() {
        // 调用创建对话框的方法,并让用户输入要查询的教师工号
        Optional<ArrayList<TextField>> result = createInputDialog("查询", "请输入要查询的教师工号");

        if (result.isPresent()) {
            // 用户点击了 "确定" 按钮,获取输入的工号
            ArrayList<TextField> idField = result.get();
            String workId = idField.get(0).getText();


            // 根据工号从数据库中查询对应的教师信息
            TeacherInformation teacher = queryById(workId);

            if (teacher == null) {
                // 如果没有查询到对应的教师信息,提示用户并返回
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setTitle("错误");
                alert.setHeaderText("未找到对应的教师信息");
                alert.setContentText("请检查输入的工号是否正确!");
                alert.showAndWait();
            } else {
                // 创建一个新的对话框,显示查询到的教师信息
                Dialog<String> infoDialog = new Dialog<>();
                infoDialog.setTitle("查询结果");
                infoDialog.setHeaderText(null);

                // 创建文本区域显示教师信息
                TextArea textArea = new TextArea();
                textArea.setEditable(false);
                textArea.appendText("姓名: " + teacher.getName() + "\n");
                textArea.appendText("性别: " + teacher.getGender() + "\n");
                textArea.appendText("年龄: " + teacher.getAge() + "\n");
                textArea.appendText("工号: " + teacher.getWorkid() + "\n");
                textArea.appendText("职称: " + teacher.getPosition() + "\n");
                textArea.appendText("工作时间: " + teacher.getWorktime() + "\n");

                // 将文本区域添加到对话框中
                infoDialog.getDialogPane().setContent(textArea);

                // 添加 "确定" 按钮
                infoDialog.getDialogPane().getButtonTypes().add(ButtonType.OK);

                // 显示对话框并等待用户响应
                infoDialog.showAndWait();
            }
        }
    }

    //删除教师
    private void deleteTeacher() {
        // 调用创建对话框的方法,并让用户输入要删除的教师工号
        Optional<ArrayList<TextField>> result = createInputDialog("删除", "请输入要删除的教师工号");

        if (result.isPresent()) {
            // 用户点击了 "确定" 按钮,获取输入的工号
            ArrayList<TextField> idField = result.get();
            String workId = idField.get(0).getText();


            // 根据工号从数据库中查询对应的教师信息
            TeacherInformation teacher = queryById(workId);

            if (teacher == null) {
                // 如果没有查询到对应的教师信息,提示用户并返回
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setTitle("错误");
                alert.setHeaderText("未找到对应的教师信息");
                alert.setContentText("请检查输入的工号是否正确!");
                alert.showAndWait();
            } else {
                // 执行删除操作
                if (connect.deleteTeacherById(workId)) {
                    // 删除成功,提示用户
                    Alert successAlert = new Alert(Alert.AlertType.INFORMATION);
                    successAlert.setTitle("删除成功");
                    successAlert.setHeaderText(null);
                    successAlert.setContentText("教师信息删除成功!");
                    successAlert.showAndWait();

                    // 刷新界面
                    showAdminScene();
                } else {
                    // 删除失败,提示用户
                    Alert errorAlert = new Alert(Alert.AlertType.ERROR);
                    errorAlert.setTitle("删除失败");
                    errorAlert.setHeaderText(null);
                    errorAlert.setContentText("教师信息删除失败!");
                    errorAlert.showAndWait();
                }
            }
        }
    }


    private void addTeacher() {
        // 创建一个对话框窗口
        Dialog<ArrayList<Control>> dialog = new Dialog<>();
        dialog.setTitle("添加教师");
        dialog.setHeaderText(null);

        // 设置对话框的按钮
        ButtonType addButton = new ButtonType("添加", ButtonBar.ButtonData.OK_DONE);
        ButtonType cancelButton = new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE);
        dialog.getDialogPane().getButtonTypes().addAll(addButton, cancelButton);

        // 创建表单布局
        GridPane formGrid = new GridPane();
        formGrid.setHgap(10);
        formGrid.setVgap(10);
        formGrid.setPadding(new Insets(20));

        // 创建表单字段和标签
        ArrayList<Control> controls = new ArrayList<>();
        ArrayList<String> labels = new ArrayList<>(Arrays.asList("姓名:", "性别:", "年龄:", "工号:", "职位:", "所属学院:", "工作时间:"));
        for (int i = 0; i < labels.size(); i++) {
            Label label = new Label(labels.get(i));
            formGrid.add(label, 0, i);
            if(i == 5){
                ComboBox<String> collegeComboBox = new ComboBox<>();
                collegeComboBox.getItems().addAll(
                        "法学院(法律事务中心)",
                        "信息工程学院",
                        "水利学院",
                        "地球科学与工程学院(地球物理研究所)",
                        "测绘与地理信息学院",
                        "材料学院",
                        "土木与交通学院(钢结构与工程研究院)",
                        "电气工程学院",
                        "能源与动力工程学院",
                        "机械学院",
                        "环境与市政工程学院",
                        "水资源学院(黄河科学研究院)",
                        "管理与经济学院(MBA教育中心)",
                        "数学与统计学院",
                        "建筑学院",
                        "电子工程学院",
                        "外国语学院",
                        "公共管理学院(MPA教育中心)",
                        "国际教育学院(语言培训中心)",
                        "马克思主义学院",
                        "艺术学院",
                        "乌拉尔学院",
                        "体育教学部"
                );
                controls.add(collegeComboBox);
                formGrid.add(collegeComboBox, 1, i);
            } else {
                TextField field = new TextField();
                formGrid.add(field, 1, i);
                controls.add(field);

                // 为年龄和工号文本框添加事件监听器,设置正则表达式
                if (i == 2 || i == 3) {
                    field.textProperty().addListener((observable, oldValue, newValue) -> {
                        if (!newValue.matches("\\d*")) {
                            field.setText(oldValue);
                        }
                    });
                }
            }
        }

        // 将表单布局设置为对话框的内容
        dialog.getDialogPane().setContent(formGrid);

        // 设置对话框的结果转换器
        dialog.setResultConverter(dialogButton -> {
            if (dialogButton == addButton) {
                // 点击添加按钮时,将输入的教师信息返回
                return controls;
            }
            return null;
        });

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

        // 处理用户操作结果
        result.ifPresent(inputs -> {
            // 获取用户输入的教师信息
            String name = ((TextField) inputs.get(0)).getText();
            String gender = ((TextField) inputs.get(1)).getText();
            int age = Integer.parseInt(((TextField) inputs.get(2)).getText());
            String workid = ((TextField) inputs.get(3)).getText();
            String position = ((TextField) inputs.get(4)).getText();
            String college = ((ComboBox<String>) inputs.get(5)).getValue();
            String worktime = ((TextField) inputs.get(6)).getText();

            // 将教师信息插入到数据库中
            try {
                connect.insertTeacher(name, gender, age, workid, position, college, worktime);
                // 插入成功后,刷新主界面
                showAdminScene();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        });
    }

    //创建对话框
    private GridPane createTeacherForm() {
        // 创建表单布局
        GridPane formGrid = new GridPane();
        formGrid.setHgap(10);
        formGrid.setVgap(10);

        // 定义表单字段和标签的名称
        ArrayList<String> fieldLabels = new ArrayList<>(Arrays.asList("姓名:", "性别:", "年龄:", "职位:", "所属学院:", "工作时间:"));
        ArrayList<TextField> fields = new ArrayList<>();

        // 使用循环创建表单字段和标签
        for (int i = 0; i < fieldLabels.size(); i++) {
            TextField field = new TextField();
            Label label = new Label(fieldLabels.get(i));
            formGrid.add(label, 0, i);
            formGrid.add(field, 1, i);
            fields.add(field);
        }

        return formGrid;
    }


    //修改教师信息
    private void amend() {
        // 调用创建对话框的方法,并让用户输入要查询的教师工号
        Optional<ArrayList<TextField>> result = createInputDialog("修改", "请输入要修改的教师工号");

        if(result.isPresent()) {
            // 用户点击了 "确定" 按钮,获取输入的工号
            ArrayList<TextField> idField = result.get();
            String workId = idField.get(0).getText();

            // 使用正则表达式限制工号只能输入数字
            if (!workId.matches("\\d+")) {
                // 如果工号不符合要求,提示用户并返回
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setTitle("错误");
                alert.setHeaderText(null);
                alert.setContentText("请输入正确的教师工号!");
                alert.showAndWait();
                return;
            }

            // 根据工号从数据库中查询对应的教师信息
            TeacherInformation teacher = queryById(workId);

            if(teacher == null) {
                // 如果没有查询到对应的教师信息,提示用户并返回
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setTitle("错误");
                alert.setHeaderText("未找到对应的教师信息");
                alert.setContentText("请检查输入的工号是否正确!");
                alert.showAndWait();
            } else {
                // 创建一个对话框窗口
                Dialog<ArrayList<TextField>> dialog1 = new Dialog<>();
                dialog1.setTitle("修改教师岗位信息");
                dialog1.setHeaderText(null);

                // 设置对话框的按钮
                ButtonType addButton = new ButtonType("修改" , ButtonBar.ButtonData.OK_DONE);
                ButtonType cancelButton = new ButtonType("取消" , ButtonBar.ButtonData.CANCEL_CLOSE);
                dialog1.getDialogPane().getButtonTypes().addAll(addButton , cancelButton);

                // 创建表单布局并获取字段对象
                GridPane formGrid = createTeacherForm();
                ArrayList<TextField> fields = new ArrayList<>(formGrid.getChildren().size());
                for(Node node : formGrid.getChildren()) {
                    if(node instanceof TextField) {
                        fields.add((TextField) node);
                    }
                }

                // 在addTeacher和amend方法中创建下拉列表,设置可选项并添加到表单布局中
                ComboBox<String> collegeComboBox = new ComboBox<>();
                collegeComboBox.getItems().addAll(
                        "法学院(法律事务中心)",
                        "信息工程学院",
                        "水利学院",
                        "地球科学与工程学院(地球物理研究所)",
                        "测绘与地理信息学院",
                        "材料学院",
                        "土木与交通学院(钢结构与工程研究院)",
                        "电气工程学院",
                        "能源与动力工程学院",
                        "机械学院",
                        "环境与市政工程学院",
                        "水资源学院(黄河科学研究院)",
                        "管理与经济学院(MBA教育中心)",
                        "数学与统计学院",
                        "建筑学院",
                        "电子工程学院",
                        "外国语学院",
                        "公共管理学院(MPA教育中心)",
                        "国际教育学院(语言培训中心)",
                        "马克思主义学院",
                        "艺术学院",
                        "乌拉尔学院",
                        "体育教学部"
                );
                formGrid.add(collegeComboBox, 1, 4);

                // 使用正则表达式限制年龄只能输入数字
                TextField ageField = fields.get(2);
                ageField.textProperty().addListener((observable, oldValue, newValue) -> {
                    if (!newValue.matches("\\d*")) {
                        ageField.setText(newValue.replaceAll("[^\\d]", ""));
                    }
                });

                // 设置对话框的结果转换器
                dialog1.setResultConverter(dialogButton -> {
                    if(dialogButton == addButton) {
                        // 点击添加按钮时,将输入的教师信息返回
                        return fields;
                    }
                    return null;
                });

                // 将表单布局设置为对话框的内容
                dialog1.getDialogPane().setContent(formGrid);
                // 显示对话框并等待用户操作
                Optional<ArrayList<TextField>> result1 = dialog1.showAndWait();
                // 处理用户操作结果
                result1.ifPresent(inputs -> {
                    // 获取用户输入的教师信息
                    String name = inputs.get(0).getText();
                    String gender = inputs.get(1).getText();
                    int age = Integer.parseInt(inputs.get(2).getText());
                    String position = inputs.get(3).getText();
                    String college = collegeComboBox.getValue();
                    String worktime = inputs.get(5).getText();

                    // 将教师信息插入到数据库中
                    connect.updateTeacher(name, gender, age ,workId , position, college, worktime);
                    System.out.println("UPDATE teacherinformation SET name='" + name + "', gender='" + gender + "', age=" + age + ", position='" + position + "', worktime='" + worktime + "', college='" + college + "' WHERE workid='" + workId + "'");

                    // 刷新教师列表
                    showAdminScene();
                });
            }
        }
    }


    //根据工号查询数据库中是否有对应的教师信息
    public TeacherInformation queryById(String workId) {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        TeacherInformation teacher = null;

        try {
            // 获取数据库连接
            conn = connect.getConnection();

            // 创建 PreparedStatement 对象,并设置占位符参数
            String sql = "SELECT * FROM teacherinformation WHERE workid=?";
            stmt = conn.prepareStatement(sql);
            stmt.setString(1, workId);

            // 执行查询操作
            rs = stmt.executeQuery();

            // 处理结果集,将查询到的教师信息保存到一个 Teacher 对象中
            if (rs.next()) {
                String name = rs.getString("name");
                String gender = rs.getString("gender");
                int age = rs.getInt("age");
                String position = rs.getString("position");
                String worktime = rs.getString("worktime");
                String college = rs.getString("college");
                teacher = new TeacherInformation(name, gender, age, workId, position,worktime,college);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }  finally {
            // 关闭数据库连接,语句和结果集
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return teacher;
    }

    public void register() {
        // 创建表单布局
        GridPane formGrid = new GridPane();
        formGrid.setHgap(10);
        formGrid.setVgap(10);

        // 定义表单字段和标签的名称
        ArrayList<String> fieldLabels = new ArrayList<>(Arrays.asList("账户", "密码", "工号"));
        ArrayList<TextField> fields = new ArrayList<>();

        // 使用循环创建表单字段和标签
        for (int i = 0; i < fieldLabels.size(); i++) {
            TextField field = new TextField();
            Label label = new Label(fieldLabels.get(i));
            formGrid.add(label, 0, i);
            formGrid.add(field, 1, i);
            fields.add(field);

            // 添加事件监听器,验证输入的内容是否符合要求
            if (i == 0 || i == 1) {
                field.textProperty().addListener((observable, oldValue, newValue) -> {
                    if (!newValue.matches("[a-zA-Z0-9]*")) {
                        field.setText(oldValue);
                    }
                });
            }
            else {
                field.textProperty().addListener((observable, oldValue, newValue) -> {
                    if (!newValue.matches("[0-9]*")) {
                        field.setText(oldValue);
                    }
                });
            }
        }

        // 显示对话框,并等待用户点击按钮
        Dialog<ButtonType> dialog = new Dialog<>();
        dialog.setTitle("注册账户");
        dialog.getDialogPane().setContent(formGrid);
        // 添加OK和Cancel按钮
        ButtonType okButton = new ButtonType("确定", ButtonBar.ButtonData.OK_DONE);
        ButtonType cancelButton = new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE);
        dialog.getDialogPane().getButtonTypes().addAll(okButton, cancelButton);



        // 等待用户点击按钮并获取结果
        Optional<ButtonType> result = dialog.showAndWait();

        if (result.isPresent() && result.get() == okButton) {
            String account = fields.get(0).getText();
            String password = fields.get(1).getText();
            String workId = fields.get(2).getText();
            // 检查用户名是否已存在
            if (checkNameExist(account)) {
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setTitle("错误");
                alert.setHeaderText(null);
                alert.setContentText("用户名已存在!");
                alert.showAndWait();
                return;
            }

            // 注册新用户
            if (createTeacherAccount(account, password, workId)) {
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setTitle("提示");
                alert.setHeaderText(null);
                alert.setContentText("注册成功!");
                alert.showAndWait();
            } else {
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setTitle("错误");
                alert.setHeaderText(null);
                alert.setContentText("注册失败!");
                alert.showAndWait();
            }
        }
    }

    //将创建的新用户添加到数据库中
    public boolean createTeacherAccount(String account, String password,String workId) {
        String sql = "INSERT INTO teacher (account, password, workid) VALUES (?, ? ,?)";
        try (Connection conn = connect.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            stmt.setString(1, account);
            stmt.setString(2, password);
            stmt.setString(3, workId);
            int result = stmt.executeUpdate();
            return result > 0;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    private boolean checkNameExist(String name) {
        boolean result = false;
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = connect.getConnection();
            // 执行查询语句
            String sql = "SELECT account FROM teacher";
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);

            // 判断是否有和name相同的值
            while (rs.next()) {
                String account = rs.getString("account");
                if (account.equals(name)) {
                    result = true;
                    break;
                }
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 关闭数据库连接
            try {
                if (rs != null) {
                    rs.close();
                }
                if (stmt != null) {
                    stmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        return result;
    }

    //创建一个对话框
    public Optional<ArrayList<TextField>> createInputDialog(String title, String headerText) {
        Dialog<ButtonType> dialog = new Dialog<>();
        dialog.setTitle(title);
        dialog.setHeaderText(headerText);

        // 创建工号输入框并添加到对话框中
        TextField workIdField = new TextField();
        dialog.getDialogPane().setContent(workIdField);

        // 创建 "确定" 和 "取消" 按钮并添加到对话框中
        ButtonType confirmButtonType = new ButtonType("确定", ButtonBar.ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(confirmButtonType, ButtonType.CANCEL);

        // 设置按钮的可用性
        Node confirmButton = dialog.getDialogPane().lookupButton(confirmButtonType);
        confirmButton.setDisable(true);
        workIdField.textProperty().addListener((observable, oldValue, newValue) -> {
            confirmButton.setDisable(newValue.trim().isEmpty());
        });

        // 显示对话框并等待用户响应
        Optional<ButtonType> result = dialog.showAndWait();

        if (result.isPresent() && result.get() == confirmButtonType) {
            ArrayList<TextField> fields = new ArrayList<>();
            fields.add(workIdField);
            return Optional.of(fields);
        } else {
            return Optional.empty();
        }
    }

    public static void main(String[] args) {
        launch();
    }
}
根据上述代码,帮我写以上系统的详细描述。
要求:总结设计用到的主要工具,详细介绍一下整个系统的主要功能模块。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-5 15:11:36 | 显示全部楼层
zqy173590939 发表于 2024-01-05 15:11
@FishC
package com.example.javafxmw;

import Da ...


该系统是一个教师岗位管理系统,主要用于管理员和教师登录后进行相应的操作。

设计中使用了JavaFX框架进行界面的构建,使用

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-5 15:12:03 | 显示全部楼层
FishC 发表于 2024-1-5 15:11
该系统是一个教师岗位管理系统,主要用于管理员和教师登录后进行相应的操作。

设计中使用了JavaFX框 ...

回答内容为什么被截断了?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-5 15:13:18 | 显示全部楼层
zqy173590939 发表于 2024-01-05 15:12
回答内容为什么被截断了?


非常抱歉,可能是因为回答的内容过长,导致被截断了。下面是完整的回答:

该系统使用JavaFX框架进行界

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-5 15:14:31 | 显示全部楼层
FishC 发表于 2024-1-5 15:11
该系统是一个教师岗位管理系统,主要用于管理员和教师登录后进行相应的操作。

设计中使用了JavaFX框 ...

内容没有显示完整,请给出完整内容
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-5 15:15:02 | 显示全部楼层
zqy173590939 发表于 2024-01-05 15:14
内容没有显示完整,请给出完整内容


抱歉,之前的回答有些内容被截断了。根据你提供的代码,该系统是一个教师岗位管理系统,主要由管理员和

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-19 03:25

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表