|
楼主 |
发表于 2023-12-31 16:14:05
|
显示全部楼层
@FishC
package com.example.javafxmw;
import gaijin3.*;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import java.io.IOException;
import java.sql.*;
import java.util.Optional;
public class HelloApplication extends Application
{
// 定义全局变量
//定义一个TextArea控件作为全局变量
TextArea infoTextArea = new TextArea();
Button viewAccuracyButton = new Button("View Accuracy");
FlowPane flowPane = new FlowPane();
ScrollPane scrollPane = new ScrollPane();// 创建一个滚动面板对象
private int maxID = 0;
@Override
public void start(Stage stage) throws IOException {
MenuItem generateMenuItem = new MenuItem("Generate");
// 事件处理器代码
generateMenuItem.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
// 创建一个警示对话框
TextInputDialog dialog = new TextInputDialog("5");
dialog.setTitle("请输入算式数量");
dialog.setHeaderText(null);
dialog.setContentText("算式数量:");
// 显示对话框,并获取用户输入的算式数量
Optional<String> result = dialog.showAndWait();
if (result.isPresent())
{
int n = Integer.parseInt(result.get());
// 生成算式
EquationCollection equationCollection = generateEquations(n);
// 清空之前的内容
flowPane.getChildren().clear();
// 遍历算式集合并显示在GUI中
for (IEquation equation : equationCollection)
{
maxID++; // id自增
Label idLabel = new Label(String.valueOf(maxID)); // 获取当前最大ID,并将新的算式ID设为其加1
Label equationLabel = new Label(equation.toString());
TextField answerField = new TextField(); // 创建一个新的文本框
HBox equationBox = new HBox(10, idLabel, new Label("、"), equationLabel, answerField); // 将算式ID标签、顿号、算式标签和文本框放入水平布局
flowPane.getChildren().add(equationBox); // 将水平布局添加到 flowPane 中
}
// 连接数据库
connectDatabase();
}
}
});
MenuItem saveMenuItem = new MenuItem("Save");
saveMenuItem.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
saveEquations();
connectDatabase();
}
});
MenuItem readMenuItem = new MenuItem("Read");
readMenuItem.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
flowPane.getChildren().clear(); // 清空当前GUI界面
showAlert("习题已读取");
displayAllEquationsFromDatabase();
}
});
MenuItem checkMenuItem = new MenuItem("Check");
checkMenuItem.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
// 检查习题
checkEquations();
}
});
// View Accuracy按钮的点击事件监听器
viewAccuracyButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
// 显示饼状图
showAccuracyChart();
}
});
Menu fileMenu = new Menu("File");
Menu saveMenu = new Menu("SaveEquation");
Menu readMenu = new Menu("ReadEquation");
Menu checkMenu = new Menu("CheckEquation");
fileMenu.getItems().addAll(generateMenuItem);
saveMenu.getItems().add(saveMenuItem);
readMenu.getItems().add(readMenuItem);
checkMenu.getItems().add(checkMenuItem);
MenuBar menuBar = new MenuBar();
menuBar.getMenus().addAll(fileMenu);
menuBar.getMenus().add(saveMenu);
menuBar.getMenus().add(readMenu);
menuBar.getMenus().add(checkMenu);
flowPane.setHgap(50);
flowPane.setVgap(30);
flowPane.setPadding(new Insets(20));
flowPane.setPrefSize(800, 560); // 设置 FlowPane 的大小
BorderPane borderPane = new BorderPane();
borderPane.setTop(menuBar);
borderPane.setCenter(flowPane);
//为了解决题目生成或多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(0, 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(0, 0, 20, 0));
borderPane.setBottom(showbottomBox);
}
public static void main(String[] args) {
launch();
}
// 生成算式的方法
public EquationCollection generateEquations(int n) {
EquationCollection equationCollection = new EquationCollection();
EquationCheckerOfRange equationChecker = new EquationCheckerOfRange(0, 100);
equationCollection.generate(n, equationChecker);
return equationCollection;
}
// 连接数据库的方法
public void connectDatabase() {
Connection conn = null;
Statement stmt = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
"root", "Zqy173590939");
DatabaseMetaData dbMeta = conn.getMetaData();
System.out.println("当前用户:" + dbMeta.getUserName());
System.out.println("驱动版本:" + dbMeta.getDriverVersion());
System.out.println("MySQL版本:" + dbMeta.getDatabaseProductVersion());
stmt = conn.createStatement();
// 查询最大ID值
ResultSet rs = stmt.executeQuery("SELECT MAX(id) FROM equationtable");
if (rs.next()) {
maxID = rs.getInt(1);
}
} catch (SQLException se) {
se.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (stmt != null)
stmt.close();
if (conn != null)
conn.close();
} catch (SQLException se) {
se.printStackTrace();
}
}
System.out.println("Goodbye!");
}
private void saveEquations() {
Connection conn = null;
PreparedStatement pstmt = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/rjgzdatabase?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
"root", "Zqy173590939");
for (Node node : flowPane.getChildren()) {
if (node instanceof HBox) {
HBox equationBox = (HBox) node;
Label idLabel = (Label) equationBox.getChildren().get(0); // 获取算式ID标签
Label equationLabel = (Label) equationBox.getChildren().get(2);
TextField answerField = (TextField) equationBox.getChildren().get(3);
String equation = equationLabel.getText();
String answerText = answerField.getText();
// 检查答案字段是否为空
int answer = 0;
if (!answerText.isEmpty()) {
answer = Integer.parseInt(answerText);
}
// 计算正确结果
int result = calculateResult(equation);
// 保存到数据库
String sql = "INSERT INTO equationtable (id, Operand1, Operator, Operand2, Result) VALUES (?, ?, ?, ?, ?)";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, Integer.parseInt(idLabel.getText())); // 将算式ID插入到数据库中
pstmt.setInt(2, getOperand1(equation));
pstmt.setString(3, getOperator(equation));
pstmt.setInt(4, getOperand2(equation));
pstmt.setInt(5, result);
pstmt.executeUpdate();
}
}
System.out.println("算式保存成功!!!");
showAlert("保存成功!");
} catch (SQLException se) {
se.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (pstmt != null)
pstmt.close();
if (conn != null)
conn.close();
} catch (SQLException se) {
se.printStackTrace();
}
}
System.out.println("Goodbye!");
}
private int calculateResult(String equation) {
String[] parts = equation.split(" ");
int operand1 = Integer.parseInt(parts[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();
}
}
为了解决生成题目太多无法显示的问题,我把flowpane添加到了scrollPane,检查checkequations方法,为什么点击check按钮后功能不能正常使用了 |
|