|
|
@@ -0,0 +1,252 @@
|
|
|
+package space.anyi.autoInputRobot.ui;
|
|
|
+
|
|
|
+import javafx.application.Application;
|
|
|
+import javafx.application.Platform;
|
|
|
+import javafx.geometry.Insets;
|
|
|
+import javafx.geometry.Pos;
|
|
|
+import javafx.scene.Scene;
|
|
|
+import javafx.scene.control.*;
|
|
|
+import javafx.scene.control.Dialog;
|
|
|
+import javafx.scene.control.DialogPane;
|
|
|
+import javafx.scene.image.Image;
|
|
|
+import javafx.scene.layout.HBox;
|
|
|
+import javafx.scene.layout.VBox;
|
|
|
+import javafx.scene.robot.Robot;
|
|
|
+import javafx.stage.FileChooser;
|
|
|
+import javafx.stage.Stage;
|
|
|
+import space.anyi.autoInputRobot.core.AutoInputRobot;
|
|
|
+import space.anyi.autoInputRobot.exception.ContentEmptyException;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @ProjectName: AutoInputRobot
|
|
|
+ * @FileName: View
|
|
|
+ * @Author: 杨逸
|
|
|
+ * @Data:2025/11/12 19:01
|
|
|
+ * @Description: 自动输入窗口
|
|
|
+ */
|
|
|
+public class View extends Application {
|
|
|
+ private final Robot robot = new Robot();
|
|
|
+ private TextField filePathField;
|
|
|
+ private TextField delayField;
|
|
|
+ private Button selectFileButton;
|
|
|
+ private Button startButton;
|
|
|
+ private Label statusLabel;
|
|
|
+ private File selectedFile;
|
|
|
+ private boolean isInputting = false; // 标记是否正在输入
|
|
|
+ private CheckBox alwaysOnTopCheckBox; // 窗口置顶复选框
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void start(Stage primaryStage) {
|
|
|
+ primaryStage.setTitle("自动输入机器人");
|
|
|
+ primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("/icon.jpg")));
|
|
|
+ // 创建UI组件
|
|
|
+ filePathField = new TextField();
|
|
|
+ filePathField.setPromptText("请选择要输入的文件");
|
|
|
+ filePathField.setEditable(false);
|
|
|
+ filePathField.setPrefWidth(300);
|
|
|
+
|
|
|
+ delayField = new TextField("5000");
|
|
|
+ delayField.setPromptText("延迟时间(毫秒)");
|
|
|
+ delayField.setPrefWidth(100);
|
|
|
+
|
|
|
+ selectFileButton = new Button("选择文件");
|
|
|
+ startButton = new Button("开始输入");
|
|
|
+ statusLabel = new Label("请选择文件并设置延迟时间");
|
|
|
+ alwaysOnTopCheckBox = new CheckBox("窗口置顶");
|
|
|
+
|
|
|
+ // 创建布局
|
|
|
+ HBox fileSelectionBox = new HBox(10);
|
|
|
+ fileSelectionBox.getChildren().addAll(filePathField, selectFileButton);
|
|
|
+ fileSelectionBox.setAlignment(Pos.CENTER_LEFT);
|
|
|
+
|
|
|
+ HBox delayBox = new HBox(10);
|
|
|
+ delayBox.getChildren().addAll(new Label("延迟时间(毫秒):"), delayField);
|
|
|
+ delayBox.setAlignment(Pos.CENTER_LEFT);
|
|
|
+
|
|
|
+ HBox buttonBox = new HBox(10);
|
|
|
+ buttonBox.getChildren().addAll(startButton);
|
|
|
+ buttonBox.setAlignment(Pos.CENTER);
|
|
|
+
|
|
|
+ HBox optionsBox = new HBox(10);
|
|
|
+ optionsBox.getChildren().addAll(alwaysOnTopCheckBox);
|
|
|
+ optionsBox.setAlignment(Pos.CENTER_LEFT);
|
|
|
+
|
|
|
+ VBox root = new VBox(15);
|
|
|
+ root.setPadding(new Insets(20));
|
|
|
+ root.getChildren().addAll(
|
|
|
+ new Label("自动输入机器人"),
|
|
|
+ fileSelectionBox,
|
|
|
+ delayBox,
|
|
|
+ optionsBox,
|
|
|
+ buttonBox,
|
|
|
+ statusLabel
|
|
|
+ );
|
|
|
+ root.setAlignment(Pos.CENTER);
|
|
|
+
|
|
|
+ // 设置按钮事件
|
|
|
+ selectFileButton.setOnAction(e -> selectFile(primaryStage));
|
|
|
+ startButton.setOnAction(e -> startAutoInput());
|
|
|
+
|
|
|
+ // 设置复选框事件
|
|
|
+ alwaysOnTopCheckBox.setOnAction(e -> primaryStage.setAlwaysOnTop(alwaysOnTopCheckBox.isSelected()));
|
|
|
+
|
|
|
+ // 初始状态设置
|
|
|
+ startButton.setDisable(true);
|
|
|
+
|
|
|
+ // 创建场景并显示
|
|
|
+ Scene scene = new Scene(root, 400, 250);
|
|
|
+ primaryStage.setScene(scene);
|
|
|
+ primaryStage.setResizable(false);
|
|
|
+
|
|
|
+ // 设置窗口关闭事件处理器
|
|
|
+ primaryStage.setOnCloseRequest(event -> {
|
|
|
+ if (isInputting) {
|
|
|
+ Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
|
|
+ alert.setTitle("确认关闭");
|
|
|
+ alert.setHeaderText("自动输入正在进行中");
|
|
|
+ alert.setContentText("关闭窗口将中断自动输入过程,确定要关闭吗?");
|
|
|
+
|
|
|
+ ButtonType okButton = new ButtonType("确定关闭", ButtonBar.ButtonData.OK_DONE);
|
|
|
+ ButtonType cancelButton = new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE);
|
|
|
+ alert.getButtonTypes().setAll(okButton, cancelButton);
|
|
|
+
|
|
|
+ // 显示对话框并等待用户响应
|
|
|
+ alert.showAndWait().ifPresent(response -> {
|
|
|
+ if (response == cancelButton) {
|
|
|
+ event.consume(); // 取消关闭事件
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ primaryStage.show();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 选择文件
|
|
|
+ */
|
|
|
+ private void selectFile(Stage primaryStage) {
|
|
|
+ FileChooser fileChooser = new FileChooser();
|
|
|
+ fileChooser.setTitle("选择要输入的文件");
|
|
|
+ fileChooser.getExtensionFilters().addAll(
|
|
|
+ new FileChooser.ExtensionFilter("文本文件", "*.txt"),
|
|
|
+ new FileChooser.ExtensionFilter("所有文件", "*.*")
|
|
|
+ );
|
|
|
+
|
|
|
+ selectedFile = fileChooser.showOpenDialog(primaryStage);
|
|
|
+ if (selectedFile != null) {
|
|
|
+ // 确保选择的是文件而不是文件夹
|
|
|
+ if (selectedFile.isFile()) {
|
|
|
+ filePathField.setText(selectedFile.getAbsolutePath());
|
|
|
+ startButton.setDisable(false);
|
|
|
+ statusLabel.setText("文件已选择: " + selectedFile.getName());
|
|
|
+ } else {
|
|
|
+ statusLabel.setText("请选择文件,而不是文件夹");
|
|
|
+ selectedFile = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 开始自动输入
|
|
|
+ */
|
|
|
+ private void startAutoInput() {
|
|
|
+ if (selectedFile == null) {
|
|
|
+ statusLabel.setText("请先选择文件");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ int delay = Integer.parseInt(delayField.getText());
|
|
|
+ if (delay < 0) {
|
|
|
+ statusLabel.setText("延迟时间必须为正数");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ statusLabel.setText("准备开始自动输入...");
|
|
|
+ startButton.setDisable(true);
|
|
|
+ selectFileButton.setDisable(true);
|
|
|
+ isInputting = true; // 标记开始输入
|
|
|
+
|
|
|
+ // 在新线程中执行自动输入,避免阻塞UI
|
|
|
+ final String absolutePath = selectedFile.getAbsolutePath();
|
|
|
+ new Thread(() -> {
|
|
|
+ try {
|
|
|
+ AutoInputRobot autoInputRobot = new AutoInputRobot(robot,delay, absolutePath);
|
|
|
+ //输入完成的事件监听器
|
|
|
+ autoInputRobot.addFinishListener(finishEvent -> {
|
|
|
+ System.out.println("触发"+System.currentTimeMillis());
|
|
|
+ Platform.runLater(()->{
|
|
|
+ statusLabel.setText("自动输入完成!");
|
|
|
+ startButton.setDisable(false);
|
|
|
+ selectFileButton.setDisable(false);
|
|
|
+ isInputting = false; // 标记输入结束
|
|
|
+ });
|
|
|
+ });
|
|
|
+ System.out.println("开始"+System.currentTimeMillis());
|
|
|
+ autoInputRobot.startAutoInput();
|
|
|
+
|
|
|
+ } catch (ContentEmptyException e) {
|
|
|
+ Platform.runLater(() -> {
|
|
|
+ showExceptionDialog("文件内容为空", e);
|
|
|
+ statusLabel.setText("错误: 文件内容为空");
|
|
|
+ startButton.setDisable(false);
|
|
|
+ selectFileButton.setDisable(false);
|
|
|
+ isInputting = false; // 标记输入结束
|
|
|
+ });
|
|
|
+ } catch (Exception e) {
|
|
|
+ Platform.runLater(() -> {
|
|
|
+ showExceptionDialog("发生异常", e);
|
|
|
+ statusLabel.setText("错误: " + e.getMessage());
|
|
|
+ startButton.setDisable(false);
|
|
|
+ selectFileButton.setDisable(false);
|
|
|
+ isInputting = false; // 标记输入结束
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }).start();
|
|
|
+
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ statusLabel.setText("请输入有效的延迟时间");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 显示异常信息的弹窗
|
|
|
+ */
|
|
|
+ private void showExceptionDialog(String title, Exception e) {
|
|
|
+ // 创建自定义对话框
|
|
|
+ Dialog<Void> dialog = new Dialog<>();
|
|
|
+ dialog.setTitle(title);
|
|
|
+ dialog.setHeaderText(null);
|
|
|
+
|
|
|
+ // 创建文本域显示完整异常信息
|
|
|
+ TextArea textArea = new TextArea();
|
|
|
+ textArea.setEditable(false);
|
|
|
+ textArea.setWrapText(true);
|
|
|
+
|
|
|
+ // 构建异常信息字符串
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ sb.append("异常类型: ").append(e.getClass().getSimpleName()).append("\n");
|
|
|
+ sb.append("异常信息: ").append(e.getMessage()).append("\n\n");
|
|
|
+
|
|
|
+ // 添加堆栈跟踪
|
|
|
+ sb.append("堆栈跟踪:\n");
|
|
|
+ for (StackTraceElement element : e.getStackTrace()) {
|
|
|
+ sb.append(" at ").append(element.toString()).append("\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ textArea.setText(sb.toString());
|
|
|
+ textArea.setPrefSize(600, 400);
|
|
|
+
|
|
|
+ // 设置对话框内容
|
|
|
+ DialogPane dialogPane = dialog.getDialogPane();
|
|
|
+ dialogPane.setContent(textArea);
|
|
|
+ dialogPane.getButtonTypes().add(ButtonType.OK);
|
|
|
+
|
|
|
+ // 显示对话框
|
|
|
+ dialog.showAndWait();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|