diff --git a/.idea/misc.xml b/.idea/misc.xml index 1ce6b8b..1e02737 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - diff --git a/src/main/java/top/r3944realms/docchecktoolrefactored/JavaFxApplication.java b/src/main/java/top/r3944realms/docchecktoolrefactored/JavaFxApplication.java index f6d66ea..d0782cf 100644 --- a/src/main/java/top/r3944realms/docchecktoolrefactored/JavaFxApplication.java +++ b/src/main/java/top/r3944realms/docchecktoolrefactored/JavaFxApplication.java @@ -12,7 +12,7 @@ public class JavaFxApplication extends Application { @Override public void init() throws Exception { super.init(); - System.setVersion("1.0.0.3-beta"); + System.setVersion("1.0.0.4"); } @Override diff --git a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/SceneManager.java b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/SceneManager.java index 40645e2..542a801 100644 --- a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/SceneManager.java +++ b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/SceneManager.java @@ -69,6 +69,9 @@ public class SceneManager { mainController = loader.getController(); // 保存控制器引用 Scene newScene = new Scene(root, 1200, 900); + String dialogCssPath = Objects.requireNonNull(Main.class.getResource("/css/inner/dialog.css")).toExternalForm(); + newScene.getStylesheets().addAll(dialogCssPath); + applyFadeTransition(root); primaryStage.setScene(newScene); @@ -96,10 +99,14 @@ public class SceneManager { Stage settingStage = new Stage(); settingStage.getIcons().add(logo); settingStage.setTitle("数字化验收工具 - 设置"); - Scene scene = new Scene(root, 300, 206); + Scene scene = new Scene(root, 362, 332); settingStage.setScene(scene); // 默认大小可调 settingStage.initOwner(primaryStage); // 设置父窗口 settingStage.initModality(Modality.WINDOW_MODAL); + + String dialogCssPath = Objects.requireNonNull(Main.class.getResource("/css/inner/dialog.css")).toExternalForm(); + scene.getStylesheets().addAll(dialogCssPath); + settingStage.setResizable(false); settingStage.centerOnScreen(); @@ -139,6 +146,8 @@ public class SceneManager { Parent root = FXMLLoader.load(Objects.requireNonNull(Main.class.getResource(fxmlPath))); Scene newScene = new Scene(root, width, height); + String dialogCssPath = Objects.requireNonNull(Main.class.getResource("/css/inner/dialog.css")).toExternalForm(); + newScene.getStylesheets().addAll(dialogCssPath); // 淡入效果 applyFadeTransition(root); diff --git a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/PathCheckPaneController.java b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/PathCheckPaneController.java index 7f397be..0ea40e3 100644 --- a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/PathCheckPaneController.java +++ b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/PathCheckPaneController.java @@ -142,7 +142,7 @@ public class PathCheckPaneController implements Initializable { result2TA.setText("未选择保存位置"); log.warn(LoggerMarker.DEBUG_MARKER, "用户未选择任何文件"); DialogUtil.showWarningDialog("警告", "操作有误", "未选择保存位置"); - generateLogicalAddress2B.setDisable(true); + generateLogicalAddress2B.setDisable(false); return; } System.setLastModifiedFile(outputFile); diff --git a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/utils/DialogUtil.java b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/utils/DialogUtil.java index 984b70c..d68747b 100644 --- a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/utils/DialogUtil.java +++ b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/utils/DialogUtil.java @@ -2,16 +2,29 @@ package top.r3944realms.docchecktoolrefactored.ui.utils; import javafx.application.Platform; import javafx.scene.control.*; +import javafx.scene.image.Image; import javafx.scene.layout.GridPane; import javafx.scene.layout.Priority; +import javafx.stage.Stage; import javafx.stage.Window; +import top.r3944realms.docchecktoolrefactored.Main; import java.util.Optional; +import java.util.Objects; /** * 对话框工具类 */ public class DialogUtil { + // -------------------------- 1. 全局CSS路径定义 -------------------------- + // 定义dialog-util.css的资源路径(需与项目中CSS文件实际路径一致) + private static final String DIALOG_CSS_PATH = Objects.requireNonNull( + Main.class.getResource("/css/inner/dialog.css") + ).toExternalForm(); + + private static final Image DIALOG_ICON = new Image( + Objects.requireNonNull(Main.class.getResourceAsStream("/img/logo256x.ico")) + ); /** * Show exit confirmation boolean. * @@ -21,6 +34,7 @@ public class DialogUtil { public static boolean showExitConfirmation(Window owner) { return showConfirmationDialog("确认退出", "您确定要退出程序吗?", "请确认您的操作"); } + /** * Show exit confirmation boolean. * @@ -40,13 +54,19 @@ public class DialogUtil { * @return the boolean */ public static boolean showConfirmationDialog(String title, String header, String content) { + // 创建确认对话框 Alert alert = new Alert(Alert.AlertType.CONFIRMATION); + // -------------------------- 2. 绑定CSS + 添加类型标识 -------------------------- + bindDialogCss(alert, Alert.AlertType.CONFIRMATION); + setAlertIcon(alert); + alert.setTitle(title); alert.setHeaderText(header); alert.setContentText(content); ButtonType yesButton = new ButtonType("是", ButtonBar.ButtonData.YES); ButtonType noButton = new ButtonType("否", ButtonBar.ButtonData.NO); alert.getButtonTypes().setAll(yesButton, noButton); + Optional result = alert.showAndWait(); return result.isPresent() && result.get() == yesButton; } @@ -61,6 +81,7 @@ public class DialogUtil { public static void showInformationDialog(String title, String header, String content) { Platform.runLater(() -> { Alert alert = createAlert(Alert.AlertType.INFORMATION, title, header, content); + setAlertIcon(alert); alert.showAndWait(); }); } @@ -75,6 +96,7 @@ public class DialogUtil { public static void showWarningDialog(String title, String header, String content) { Platform.runLater(() -> { Alert alert = createAlert(Alert.AlertType.WARNING, title, header, content); + setAlertIcon(alert); alert.showAndWait(); }); } @@ -89,14 +111,20 @@ public class DialogUtil { public static void showErrorDialog(String title, String header, String content) { Platform.runLater(() -> { Alert alert = createAlert(Alert.AlertType.ERROR, title, header, content); + setAlertIcon(alert); alert.showAndWait(); }); } + /** * 创建支持长文本的对话框 */ private static Alert createAlert(Alert.AlertType alertType, String title, String header, String content) { Alert alert = new Alert(alertType); + // -------------------------- 2. 绑定CSS + 添加类型标识 -------------------------- + bindDialogCss(alert, alertType); + setAlertIcon(alert); + alert.setTitle(title); alert.setHeaderText(header); @@ -109,19 +137,23 @@ public class DialogUtil { textArea.setMaxWidth(Double.MAX_VALUE); textArea.setMaxHeight(Double.MAX_VALUE); - // 设置文本区域样式 - textArea.setStyle("-fx-font-family: monospace; -fx-font-size: 12px;"); + // -------------------------- 3. 移除内联样式,由CSS控制 -------------------------- + // 原内联样式:textArea.setStyle("-fx-font-family: monospace; -fx-font-size: 12px;"); + // 改为添加样式类,对应CSS中的 .dialog-pane .content .grid-pane .text-area + textArea.getStyleClass().add("dialog-text-area"); GridPane.setVgrow(textArea, Priority.ALWAYS); GridPane.setHgrow(textArea, Priority.ALWAYS); GridPane expContent = new GridPane(); expContent.setMaxWidth(Double.MAX_VALUE); - expContent.add(new Label("详细信息:"), 0, 0); + // 为Label添加样式类,对应CSS中的 .dialog-pane .content .grid-pane .label + Label detailLabel = new Label("详细信息:"); + detailLabel.getStyleClass().add("dialog-detail-label"); + expContent.add(detailLabel, 0, 0); expContent.add(textArea, 0, 1); alert.getDialogPane().setContent(expContent); - // 设置对话框大小 alert.getDialogPane().setPrefSize(600, 400); } else { @@ -138,6 +170,10 @@ public class DialogUtil { public static void showDetailedErrorDialog(String title, String summary, String details) { Platform.runLater(() -> { Alert alert = new Alert(Alert.AlertType.ERROR); + // -------------------------- 2. 绑定CSS + 添加类型标识 -------------------------- + bindDialogCss(alert, Alert.AlertType.ERROR); + setAlertIcon(alert); + alert.setTitle(title); alert.setHeaderText(summary); @@ -147,14 +183,18 @@ public class DialogUtil { textArea.setWrapText(true); textArea.setMaxWidth(Double.MAX_VALUE); textArea.setMaxHeight(Double.MAX_VALUE); - textArea.setStyle("-fx-font-family: monospace; -fx-font-size: 11px;"); + + // -------------------------- 3. 移除内联样式,由CSS控制 -------------------------- + textArea.getStyleClass().add("dialog-text-area"); GridPane.setVgrow(textArea, Priority.ALWAYS); GridPane.setHgrow(textArea, Priority.ALWAYS); GridPane expContent = new GridPane(); expContent.setMaxWidth(Double.MAX_VALUE); - expContent.add(new Label("错误详情:"), 0, 0); + Label errorLabel = new Label("错误详情:"); + errorLabel.getStyleClass().add("dialog-detail-label"); + expContent.add(errorLabel, 0, 0); expContent.add(textArea, 0, 1); alert.getDialogPane().setContent(expContent); @@ -169,6 +209,10 @@ public class DialogUtil { public static void showDetailedWarningDialog(String title, String summary, String details) { Platform.runLater(() -> { Alert alert = new Alert(Alert.AlertType.WARNING); + // -------------------------- 2. 绑定CSS + 添加类型标识 -------------------------- + bindDialogCss(alert, Alert.AlertType.WARNING); + setAlertIcon(alert); + alert.setTitle(title); alert.setHeaderText(summary); @@ -177,14 +221,18 @@ public class DialogUtil { textArea.setWrapText(true); textArea.setMaxWidth(Double.MAX_VALUE); textArea.setMaxHeight(Double.MAX_VALUE); - textArea.setStyle("-fx-font-family: monospace; -fx-font-size: 11px;"); + + // -------------------------- 3. 移除内联样式,由CSS控制 -------------------------- + textArea.getStyleClass().add("dialog-text-area"); GridPane.setVgrow(textArea, Priority.ALWAYS); GridPane.setHgrow(textArea, Priority.ALWAYS); GridPane expContent = new GridPane(); expContent.setMaxWidth(Double.MAX_VALUE); - expContent.add(new Label("警告详情:"), 0, 0); + Label warningLabel = new Label("警告详情:"); + warningLabel.getStyleClass().add("dialog-detail-label"); + expContent.add(warningLabel, 0, 0); expContent.add(textArea, 0, 1); alert.getDialogPane().setContent(expContent); @@ -199,6 +247,10 @@ public class DialogUtil { public static void showDetailedInformationDialog(String title, String summary, String details) { Platform.runLater(() -> { Alert alert = new Alert(Alert.AlertType.INFORMATION); + // -------------------------- 2. 绑定CSS + 添加类型标识 -------------------------- + bindDialogCss(alert, Alert.AlertType.INFORMATION); + setAlertIcon(alert); + alert.setTitle(title); alert.setHeaderText(summary); @@ -207,14 +259,18 @@ public class DialogUtil { textArea.setWrapText(true); textArea.setMaxWidth(Double.MAX_VALUE); textArea.setMaxHeight(Double.MAX_VALUE); - textArea.setStyle("-fx-font-family: monospace; -fx-font-size: 11px;"); + + // -------------------------- 3. 移除内联样式,由CSS控制 -------------------------- + textArea.getStyleClass().add("dialog-text-area"); GridPane.setVgrow(textArea, Priority.ALWAYS); GridPane.setHgrow(textArea, Priority.ALWAYS); GridPane expContent = new GridPane(); expContent.setMaxWidth(Double.MAX_VALUE); - expContent.add(new Label("详细信息:"), 0, 0); + Label infoLabel = new Label("详细信息:"); + infoLabel.getStyleClass().add("dialog-detail-label"); + expContent.add(infoLabel, 0, 0); expContent.add(textArea, 0, 1); alert.getDialogPane().setContent(expContent); @@ -222,13 +278,53 @@ public class DialogUtil { alert.showAndWait(); }); } + public static void showErrorDialog(String title, String content) { showErrorDialog(title, title, content); } + public static void showWarningDialog(String title, String content) { showWarningDialog(title, title, content); } + public static void showInformationDialog(String title, String content) { showInformationDialog(title, title, content); } -} + + /** + * 为对话框绑定CSS,并根据类型添加样式类(用于CSS差异化渲染) + * @param alert 对话框实例 + * @param alertType 对话框类型(ERROR/WARNING/INFORMATION/CONFIRMATION) + */ + private static void bindDialogCss(Alert alert, Alert.AlertType alertType) { + DialogPane dialogPane = alert.getDialogPane(); + // 添加dialog-util.css样式 + dialogPane.getStylesheets().add(DIALOG_CSS_PATH); + // 根据对话框类型添加样式类(对应CSS中的 .dialog-pane:error/.dialog-pane:warning 等) + switch (alertType) { + case ERROR: + dialogPane.getStyleClass().add("error"); + break; + case WARNING: + dialogPane.getStyleClass().add("warning"); + break; + case INFORMATION: + dialogPane.getStyleClass().add("information"); + break; + case CONFIRMATION: + dialogPane.getStyleClass().add("confirmation"); + break; + default: + break; + } + // 为对话框面板添加基础样式类(确保CSS选择器能匹配) + dialogPane.getStyleClass().add("dialog-pane"); + } + // 封装设置Alert图标方法 + private static void setAlertIcon(Alert alert) { + // 间接获取Alert对应的Stage + Stage alertStage = (Stage) alert.getDialogPane().getScene().getWindow(); + // 添加图标(可添加多个尺寸,系统自动适配) + alertStage.getIcons().add(DIALOG_ICON); + } +} \ No newline at end of file diff --git a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/utils/ProgressBar.java b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/utils/ProgressBar.java index 790308e..7627347 100644 --- a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/utils/ProgressBar.java +++ b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/utils/ProgressBar.java @@ -4,11 +4,14 @@ import javafx.application.Platform; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; +import javafx.scene.image.Image; import javafx.scene.layout.VBox; import javafx.stage.Modality; import javafx.stage.Stage; import javafx.stage.StageStyle; +import top.r3944realms.docchecktoolrefactored.Main; +import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -24,9 +27,26 @@ public class ProgressBar { private final AtomicBoolean cancelled = new AtomicBoolean(false); private Runnable onCancelCallback; + // 进度条窗口图标 + private static final Image PROGRESS_ICON; + + // CSS样式路径 + private static final String PROGRESS_CSS; + + static { + // 初始化图标和CSS路径 + PROGRESS_ICON = new Image(Objects.requireNonNull( + Main.class.getResourceAsStream("/img/logo256x.ico") + )); + PROGRESS_CSS = Objects.requireNonNull( + Main.class.getResource("/css/inner/progress.css") + ).toExternalForm(); + } + public ProgressBar(boolean isCancelable) { this.isCancelable = isCancelable; } + public ProgressBar() { this(true); } @@ -42,18 +62,22 @@ public class ProgressBar { progressStage = new Stage(); progressStage.initOwner(ownerStage); progressStage.initStyle(StageStyle.UTILITY); + + // 设置窗口图标 + progressStage.getIcons().add(PROGRESS_ICON); + if (isCancelable) { progressStage.setOnCloseRequest(windowEvent -> { - if (!DialogUtil.showCancelConfirmation(progressStage.getOwner())) { - windowEvent.consume(); - } - else { - cancelled.set(true); - if (onCancelCallback != null) { - onCancelCallback.run(); - } - closeProgress(); + if (!DialogUtil.showCancelConfirmation(progressStage.getOwner())) { + windowEvent.consume(); + } + else { + cancelled.set(true); + if (onCancelCallback != null) { + onCancelCallback.run(); } + closeProgress(); + } }); } progressStage.initModality(Modality.APPLICATION_MODAL); @@ -88,14 +112,21 @@ public class ProgressBar { }); } } - // 布局 - VBox root = new VBox(10, messageLabel, progressBar); - if (isCancelable) root.getChildren().add(cancelButton); - root.setStyle("-fx-padding: 20; -fx-alignment: center;"); + // 布局 + VBox root = new VBox(15, messageLabel, progressBar); + root.getStyleClass().add("vbox"); // 添加样式类 + if (isCancelable) { + root.getChildren().add(cancelButton); + } + + // 应用CSS样式 Scene scene = new Scene(root); + scene.getStylesheets().add(PROGRESS_CSS); + progressStage.setScene(scene); progressStage.sizeToScene(); + progressStage.centerOnScreen(); // 居中显示 progressStage.show(); }); } @@ -153,10 +184,12 @@ public class ProgressBar { } }).start(); } + @FunctionalInterface public interface CancellableTask { void run(ProgressBar util); } + public void setOnCancel(Runnable onCancel) { if (isCancelable) { if (cancelButton != null) { diff --git a/src/main/resources/css/inner/dialog.css b/src/main/resources/css/inner/dialog.css new file mode 100644 index 0000000..a71f6c9 --- /dev/null +++ b/src/main/resources/css/inner/dialog.css @@ -0,0 +1,124 @@ +/* ================================= 全局对话框基础样式 ================================= */ +/* 对话框容器(DialogPane):统一背景、边框与阴影 */ +.dialog-pane { + -fx-background-color: white; /* 白色背景,符合主流对话框风格 */ + -fx-border-color: #DEE2E6; /* 浅灰边框,区分对话框与背景 */ + -fx-border-width: 1px; + -fx-border-radius: 8px; /* 圆角优化,避免尖锐边缘 */ + -fx-background-radius: 8px; + -fx-effect: dropshadow(gaussian, rgba(0,0,0,0.2), 10, 0, 0, 4); /* 柔和阴影,提升立体感 */ + -fx-padding: 15px; /* 内边距15px,避免内容贴边 */ +} + +/* 对话框标题栏(标题文本):统一字体与颜色 */ +.dialog-pane .header-panel .label { + -fx-font-family: "Microsoft YaHei", "SimHei", "sans-serif"; + -fx-font-size: 16px; + -fx-font-weight: bold; + -fx-text-fill: #212529; /* 深灰文本,突出标题层级 */ + -fx-padding: 0 0 10px 0; /* 下内边距10px,分隔标题与内容 */ +} + +/* 对话框内容区文本(短文本场景):优化可读性 */ +.dialog-pane .content.label { + -fx-font-family: "Microsoft YaHei", "SimHei", "sans-serif"; + -fx-font-size: 14px; + -fx-text-fill: #495057; /* 中灰文本,清晰不刺眼 */ + -fx-padding: 5px 0 15px 0; /* 上下内边距,优化内容间距 */ + -fx-wrap-text: true; /* 自动换行,避免文本溢出 */ +} + +/* 对话框图标(信息/警告/错误图标):调整大小与间距 */ +.dialog-pane .graphic-container .image-view { + -fx-fit-width: 24px; + -fx-fit-height: 24px; + -fx-padding: 0 10px 0 0; /* 右内边距10px,与文本拉开距离 */ +} + + +/* ================================= 按钮栏(ButtonBar)样式 ================================= */ +/* 按钮容器:控制按钮间距与对齐 */ +.dialog-pane .button-bar { + -fx-spacing: 10px; /* 按钮间间距10px,避免拥挤 */ + -fx-padding: 10px 0 0 0; /* 上内边距10px,分隔内容与按钮 */ + -fx-alignment: CENTER_RIGHT; /* 按钮右对齐,符合操作习惯 */ +} + +/* 通用按钮基础样式:统一尺寸与字体 */ +.dialog-pane .button { + -fx-font-family: "Microsoft YaHei", "SimHei", "sans-serif"; + -fx-font-size: 13px; + -fx-padding: 6px 16px; /* 上下6px、左右16px,优化点击区域 */ + -fx-border-radius: 4px; + -fx-background-radius: 4px; + -fx-cursor: hand; /* 鼠标悬浮为手型,提示可点击 */ +} + +/* 1. 确认按钮(“是”/“确定”):主要操作,突出显示 */ +.dialog-pane .button:default { /* 默认按钮(如YES/OK) */ + -fx-background-color: #0D6EFD; /* 蓝色主按钮,与主界面风格统一 */ + -fx-text-fill: white; + -fx-border-color: #0D6EFD; +} + +.dialog-pane .button:default:hover { + -fx-background-color: #0B5ED7; /* 加深背景色,反馈明显 */ + -fx-border-color: #0A58CA; +} + + + + +/* ================================= 带详细信息的对话框(长文本+GridPane)样式 ================================= */ +/* 详细信息容器(GridPane):控制标签与文本区域的布局 */ +.dialog-pane .content .grid-pane { + -fx-hgap: 10px; /* 列间距10px,分隔标签与文本区 */ + -fx-vgap: 8px; /* 行间距8px,优化垂直紧凑度 */ + -fx-alignment: CENTER_LEFT; /* 内容左对齐,符合阅读习惯 */ +} + +/* 详细信息标签(如“详细信息:”/“错误详情:”):统一样式 */ +.dialog-pane .content .grid-pane .label { + -fx-font-family: "Microsoft YaHei", "SimHei", "sans-serif"; + -fx-font-size: 14px; + -fx-font-weight: 500; /* 半粗体,突出标签层级 */ + -fx-text-fill: #495057; + -fx-padding: 2px 0; /* 上下内边距,避免标签贴边 */ +} + +/* 长文本显示区域(TextArea):优化代码/日志类文本显示 */ +.dialog-pane .content .grid-pane .text-area { + -fx-font-family: "Consolas", "Monaco", monospace; /* 等宽字体,适配代码/详细日志 */ + -fx-font-size: 12px; /* 等宽字体12px,保证可读性 */ + -fx-text-fill: #212529; + -fx-background-color: #F8F9FA; /* 浅灰背景,区分文本区与容器 */ + -fx-border-color: #DEE2E6; /* 浅灰边框,增加轮廓感 */ + -fx-border-radius: 4px; + -fx-background-radius: 4px; + -fx-padding: 10px; /* 内边距10px,文本不贴边 */ + -fx-wrap-text: true; /* 自动换行,避免横向滚动 */ +} + +/* TextArea聚焦时:突出边框,提示激活状态 */ +.dialog-pane .content .grid-pane .text-area:focused { + -fx-border-color: #80BDFF; /* 浅蓝色边框,符合聚焦反馈 */ + -fx-border-width: 1.5px; + -fx-effect: none; /* 移除默认聚焦阴影,避免冲突 */ +} + +/* TextArea滚动条:优化外观,减少突兀感 */ +.dialog-pane .content .grid-pane .text-area .scroll-bar:vertical, +.dialog-pane .content .grid-pane .text-area .scroll-bar:horizontal { + -fx-background-color: transparent; /* 透明背景,融入文本区 */ +} + +.dialog-pane .content .grid-pane .text-area .scroll-bar:vertical .thumb, +.dialog-pane .content .grid-pane .text-area .scroll-bar:horizontal .thumb { + -fx-background-color: #ADB5BD; /* 中灰滑块,清晰可辨 */ + -fx-background-radius: 4px; /* 滑块圆角,优化手感 */ +} + +.dialog-pane .content .grid-pane .text-area .scroll-bar:vertical .thumb:hover, +.dialog-pane .content .grid-pane .text-area .scroll-bar:horizontal .thumb:hover { + -fx-background-color: #868E96; /* 深灰hover,反馈明显 */ +} \ No newline at end of file diff --git a/src/main/resources/css/inner/progress.css b/src/main/resources/css/inner/progress.css new file mode 100644 index 0000000..8d918ad --- /dev/null +++ b/src/main/resources/css/inner/progress.css @@ -0,0 +1,84 @@ +/* 进度条窗口主容器 */ +.vbox { + -fx-background-color: white; + -fx-border-color: #DEE2E6; + -fx-border-radius: 8px; + -fx-background-radius: 8px; + -fx-padding: 20px; +} + +/* 消息标签样式 */ +.label { + -fx-font-family: "Microsoft YaHei", "SimHei", sans-serif; + -fx-font-size: 14px; + -fx-text-fill: #495057; + -fx-wrap-text: true; + -fx-prefWidth: 300px; + -fx-alignment: center-left; +} + +/* 进度条样式 */ +.progress-bar { + -fx-pref-width: 300px; + -fx-pref-height: 8px; +} + +/* 进度条轨道 */ +.progress-bar .track { + -fx-background-color: #E9ECEF; + -fx-background-radius: 4px; + -fx-border-radius: 4px; + -fx-border-width: 0; +} + +/* 进度条填充部分 */ +.progress-bar .bar { + -fx-background-color: #0D6EFD; + -fx-background-radius: 4px; + -fx-border-radius: 4px; + -fx-background-insets: 0; +} + +/* 不确定进度状态的动画 */ +.progress-bar:indeterminate .bar { + -fx-background-color: linear-gradient( + to right, + transparent 0%, + #0D6EFD 50%, + transparent 100% + ); + -fx-background-size: 200% 100%; + -fx-animation: progress-animation 1.5s infinite; +} + +@keyframes progress-animation { + 0% { + -fx-background-position: -200% 0; + } + 100% { + -fx-background-position: 200% 0; + } +} + +/* 取消按钮样式 */ +.button { + -fx-background-color: #6C757D; + -fx-text-fill: white; + -fx-font-family: "Microsoft YaHei", "SimHei", sans-serif; + -fx-font-size: 13px; + -fx-pref-width: 80px; + -fx-pref-height: 30px; + -fx-border-radius: 4px; + -fx-background-radius: 4px; + -fx-cursor: hand; +} + +/* 取消按钮悬停效果 */ +.button:hover { + -fx-background-color: #5A6268; +} + +/* 取消按钮按压效果 */ +.button:pressed { + -fx-background-color: #495057; +} \ No newline at end of file diff --git a/src/main/resources/css/main.css b/src/main/resources/css/main.css new file mode 100644 index 0000000..ffdec0b --- /dev/null +++ b/src/main/resources/css/main.css @@ -0,0 +1,157 @@ +/* ================================= 全局基础样式 ================================= */ +/* 主容器VBox样式:统一背景与内边距 */ +VBox { + -fx-background-color: #F8F9FA; /* 浅灰背景,避免刺眼 */ + -fx-padding: 0; /* 移除默认内边距,子组件自行控制 */ + -fx-spacing: 0; /* 消除组件间默认间距,保持紧凑 */ +} + +/* 所有文本组件统一字体(避免系统字体混乱) */ +* { + -fx-font-family: "Microsoft YaHei", "SimHei", "sans-serif"; /* 适配中文显示 */ +} + + +/* ================================= 菜单栏(MenuBar)样式 ================================= */ +MenuBar { + -fx-background-color: #343A40; /* 深灰背景,突出菜单层级 */ + -fx-text-fill: white; /* 菜单文本白色 */ + -fx-pref-height: 36px; /* 固定高度,避免拉伸 */ +} + +/* 一级菜单样式 */ +Menu { + -fx-text-fill: white; + -fx-font-size: 14px; + -fx-padding: 0 15px; /* 菜单内边距,增加点击区域 */ + -fx-cursor: hand; /* 鼠标悬浮为手型,提示可点击 */ +} + +/* 一级菜单 hover 效果 */ +Menu:hover { + -fx-background-color: #495057; /* 深灰加深,反馈明显 */ +} + +/* 菜单项(MenuItem)样式 */ +MenuItem { + -fx-background-color: white; + -fx-text-fill: #212529; + -fx-font-size: 13px; + -fx-padding: 8px 25px; /* 上下8px、左右25px,优化点击区域 */ +} + +/* 菜单项 hover 效果 */ +MenuItem:hover { + -fx-background-color: #E9ECEF; /* 浅灰背景,区分选中状态 */ + -fx-text-fill: #0D6EFD; /* 蓝色文本,突出选中项 */ +} + +/* 分隔线(SeparatorMenuItem)样式 */ +SeparatorMenuItem .line { + -fx-background-color: #DEE2E6; /* 浅灰分隔线,不突兀 */ + -fx-pref-height: 1px; +} + + +/* ================================= 标签页(TabPane)样式 ================================= */ +/* 标签容器整体样式 */ +TabPane { + -fx-background-color: white; + -fx-border-color: #DEE2E6; /* 浅灰边框,区分区域 */ + -fx-border-width: 1px 0; /* 仅上下边框,左右无边框 */ + -fx-pref-height: 700px; /* 固定高度,适配1000px主容器 */ +} + +/* 标签栏(TabHeaderArea)样式:标签所在的顶部栏 */ +TabPane .tab-header-area { + -fx-background-color: white; + + -fx-border-color: #DEE2E6; + -fx-border-width: 0 0 1px 0; /* 仅底部边框,分隔标签与内容区 */ +} + +/* 单个标签(Tab)基础样式 */ +Tab { + -fx-background-color: transparent; /* 透明背景,hover时显示效果 */ + -fx-text-fill: #6C757D; /* 未选中标签文本:浅灰 */ + -fx-font-size: 15px; + -fx-padding: 8px 25px; /* 上下8px、左右25px,增加点击区域 */ + -fx-cursor: hand; +} + +/* 未选中标签 hover 效果 */ +Tab:hover { + -fx-text-fill: #0D6EFD; /* 蓝色文本,提示可点击 */ +} + +/* 选中标签(.selected)样式 */ +Tab:selected { + -fx-text-fill: #0D6EFD; /* 蓝色文本,突出选中状态 */ + -fx-underline: true; /* 下划线标识,替代默认背景 */ + -fx-underline-color: #0D6EFD; /* 下划线与文本同色 */ + -fx-underline-width: 2px; /* 下划线加粗,更明显 */ +} + +/* 标签内容区(TabContentArea)样式:标签对应的内容容器 */ +TabPane .tab-content-area { + -fx-background-color: white; + -fx-padding: 20px; /* 内边距20px,内容不贴边 */ +} + +/* 长文本标签(自定义styleClass="long-text-tab"):适配“2. 查遗漏、存储路径和命名规范” */ +Tab.long-text-tab { + -fx-padding: 8px 20px; /* 左右内边距缩减为20px,避免文本溢出 */ + -fx-font-size: 14px; /* 字体稍小,适配长文本 */ +} + +/* 首尾标签(id="startTab"、id="endTab"):可选,突出首尾步骤 */ +Tab#startTab:selected, +Tab#endTab:selected { + -fx-text-fill: #28A745; /* 绿色文本,区分首尾步骤 */ + -fx-underline-color: #28A745; +} + + +/* ================================= 导航按钮(HBox + Button)样式 ================================= */ +/* 按钮容器(HBox)样式:右对齐布局 */ +HBox { + -fx-background-color: white; + -fx-padding: 0 20px; /* 左右20px,按钮不贴边 */ +} + +/* 导航按钮(上一步/下一步)基础样式 */ +Button { + -fx-background-color: #0D6EFD; /* 蓝色主按钮 */ + -fx-text-fill: white; + -fx-font-size: 19px; /* 按FXML要求,保持19px粗体 */ + -fx-font-weight: bold; + -fx-border-radius: 6px; /* 圆角,避免尖锐 */ + -fx-background-radius: 6px; + -fx-cursor: hand; + -fx-effect: dropshadow(gaussian, rgba(0,0,0,0.1), 5, 0, 0, 2); /* 轻微阴影,增加立体感 */ +} + +/* 按钮 hover 效果:加深背景色 */ +Button:hover { + -fx-background-color: #0B5ED7; /* 深蓝色,反馈明显 */ + -fx-effect: dropshadow(gaussian, rgba(0,0,0,0.2), 5, 0, 0, 2); /* 阴影加深 */ +} + +/* 按钮按压效果:移除阴影+背景色再加深 */ +Button:pressed { + -fx-background-color: #0A58CA; + -fx-effect: none; /* 按压时无阴影,模拟“按下”质感 */ +} + +/* 上一步按钮(可选):区分颜色,避免与下一步混淆 */ +Button#prevB { + -fx-background-color: #6C757D; /* 浅灰按钮,次要操作 */ +} + +Button#prevB:hover { + -fx-background-color: #5A6268; /* 深灰 hover 色 */ +} + +Button#prevB:pressed { + -fx-background-color: #495057; +} diff --git a/src/main/resources/css/setting.css b/src/main/resources/css/setting.css new file mode 100644 index 0000000..e326dae --- /dev/null +++ b/src/main/resources/css/setting.css @@ -0,0 +1,169 @@ +/* ================================= 全局基础样式 ================================= */ +/* 主容器VBox:控制整体间距与背景 */ +VBox { + -fx-background-color: white; /* 白色背景,符合对话框简洁风格 */ + -fx-padding: 20px; /* 内边距20px,避免内容贴边 */ + -fx-spacing: 15px; /* 组件间间距15px,层次分明 */ + -fx-border-color: #DEE2E6; /* 浅灰边框,区分对话框与主界面 */ + -fx-border-width: 1px; + -fx-border-radius: 8px; /* 轻微圆角,避免尖锐 */ + -fx-effect: dropshadow(gaussian, rgba(0,0,0,0.15), 8, 0, 0, 3); /* 柔和阴影,提升立体感 */ +} + +/* 统一字体:适配中文,避免系统字体混乱 */ +* { + -fx-font-family: "Microsoft YaHei", "SimHei", "sans-serif"; + -fx-font-size: 14px; /* 基础字体大小,保证可读性 */ +} + + +/* ================================= 标题样式(“设置”Label) ================================= */ +/* 标题Label:突出显示,区分标题与内容 */ +Label[text="设置"] { + -fx-font-size: 21px; /* 按FXML要求保持21px字号 */ + -fx-font-weight: bold; + -fx-text-fill: #212529; /* 深灰文本,庄重不刺眼 */ + -fx-padding: 5px 0 10px 0; /* 上下内边距,增加标题与下方内容的距离 */ + -fx-border-color: #DEE2E6; + -fx-border-width: 0 0 1px 0; /* 底部浅灰边框,分隔标题与设置项 */ +} + + +/* ================================= 网格布局(GridPane)样式 ================================= */ +/* 网格容器:控制设置项的整体排列 */ +GridPane { + -fx-hgap: 10px; /* 列间距10px,避免标签与输入框拥挤 */ + -fx-vgap: 8px; /* 行间距8px,优化垂直紧凑度 */ + -fx-alignment: CENTER_LEFT; /* 内容左对齐,符合阅读习惯 */ +} + +/* 单位标签(“秒”):统一样式,与输入框对齐 */ +GridPane Label[text="秒"] { + -fx-text-fill: #6C757D; /* 浅灰文本,次要信息弱化 */ + -fx-alignment: CENTER_LEFT; + -fx-padding: 0 0 0 5px; /* 左内边距5px,与Spinner拉开微小距离 */ +} + + +/* ================================= 输入组件样式 ================================= */ +/* 1. 数值选择器(Spinner):优化外观与交互 */ +Spinner { + -fx-pref-width: 94px; /* 按FXML列宽适配,避免拉伸 */ + -fx-border-color: #DEE2E6; /* 浅灰边框,统一风格 */ + -fx-border-radius: 4px; + -fx-background-color: white; +} + +/* Spinner聚焦时:突出边框,提示当前激活状态 */ +Spinner:focused { + -fx-border-color: #80BDFF; /* 浅蓝色边框,符合主流UI聚焦反馈 */ + -fx-border-width: 2px; + -fx-effect: none; /* 移除默认聚焦阴影,避免冲突 */ +} + +/* Spinner按钮(上下箭头):优化尺寸与颜色 */ +Spinner .increment-arrow-button, +Spinner .decrement-arrow-button { + -fx-background-color: #F8F9FA; /* 浅灰背景,区分按钮区域 */ + -fx-border-color: #DEE2E6; + -fx-border-width: 0 0 0 1px; /* 仅左侧边框,分隔输入区与按钮区 */ +} + +/* Spinner箭头图标:加深颜色,提高辨识度 */ +Spinner .increment-arrow, +Spinner .decrement-arrow { + -fx-background-color: #495057; +} + + +/* 2. 复选框(CheckBox):优化选中状态与间距 */ +CheckBox { + -fx-text-fill: #495057; /* 中灰文本,与设置项标签一致 */ + -fx-padding: 5px 0; /* 上下内边距,增加与上下行的距离 */ + -fx-cursor: hand; /* 鼠标悬浮为手型,提示可点击 */ +} + +/* CheckBox选中时:自定义勾选颜色,突出激活状态 */ +CheckBox:selected .box { + -fx-background-color: #0D6EFD; /* 蓝色背景,与主界面按钮风格统一 */ +} + +/* CheckBox勾选图标:白色图标,与蓝色背景对比明显 */ +CheckBox:selected .mark { + -fx-background-color: white; +} + + +/* ================================= 按钮样式 ================================= */ +/* 1. 恢复默认值按钮(resetB):次要操作,风格弱化 */ +Button#resetB { + -fx-background-color: #F8F9FA; /* 浅灰背景,区分次要操作 */ + -fx-text-fill: #495057; /* 中灰文本 */ + -fx-border-color: #DEE2E6; /* 浅灰边框,增加轮廓感 */ + -fx-border-radius: 4px; + -fx-background-radius: 4px; + -fx-pref-width: 120px; /* 适配文本长度,避免按钮过短 */ + -fx-padding: 6px 12px; + -fx-cursor: hand; +} + +/* resetB hover效果:加深背景色,反馈明显 */ +Button#resetB:hover { + -fx-background-color: #E2E6EA; + -fx-border-color: #D6D8DB; +} + + +/* 2. 取消按钮(cancelB):中性操作,风格温和 */ +Button#cancelB { + -fx-background-color: white; /* 白色背景,中性风格 */ + -fx-text-fill: #495057; /* 中灰文本 */ + -fx-border-color: #DEE2E6; /* 浅灰边框 */ + -fx-border-radius: 4px; + -fx-background-radius: 4px; + -fx-pref-width: 100px; /* 按FXML要求保持100px宽度 */ + -fx-padding: 6px 12px; + -fx-cursor: hand; +} + +/* cancelB hover效果:背景色变浅,反馈清晰 */ +Button#cancelB:hover { + -fx-background-color: #F8F9FA; +} + + +/* 3. 保存按钮(saveB):主要操作,突出显示 */ +Button#saveB { + -fx-background-color: #0D6EFD; /* 蓝色主按钮,与主界面导航按钮风格统一 */ + -fx-text-fill: white; /* 白色文本,对比明显 */ + -fx-border-color: #0D6EFD; /* 蓝色边框,强化轮廓 */ + -fx-border-radius: 4px; + -fx-background-radius: 4px; + -fx-pref-width: 100px; /* 按FXML要求保持100px宽度 */ + -fx-padding: 6px 12px; + -fx-cursor: hand; +} + +/* saveB hover效果:加深背景色,提升交互感 */ +Button#saveB:hover { + -fx-background-color: #0B5ED7; + -fx-border-color: #0A58CA; +} + +/* saveB按压效果:移除多余阴影,模拟“按下”质感 */ +Button#saveB:pressed { + -fx-effect: none; +} + + +/* ================================= 按钮容器(HBox)样式 ================================= */ +/* 按钮容器:控制按钮的对齐与间距 */ +HBox { + -fx-spacing: 15px; /* 按钮间间距15px,避免拥挤 */ + -fx-padding: 5px 0 0 0; /* 上内边距5px,与上方组件拉开距离 */ +} + +/* 恢复默认值按钮的容器(左侧HBox):居中对齐 */ +HBox[alignment="CENTER"] { + -fx-padding: 5px 0 10px 0; /* 下内边距10px,增加与下方取消/保存按钮的距离 */ +} \ No newline at end of file diff --git a/src/main/resources/fxml/main-view.fxml b/src/main/resources/fxml/main-view.fxml index 5c249ec..4c28011 100644 --- a/src/main/resources/fxml/main-view.fxml +++ b/src/main/resources/fxml/main-view.fxml @@ -12,7 +12,7 @@ - + @@ -27,7 +27,7 @@ - + diff --git a/src/main/resources/fxml/setting-view.fxml b/src/main/resources/fxml/setting-view.fxml index 0d4ff1c..1b95bab 100644 --- a/src/main/resources/fxml/setting-view.fxml +++ b/src/main/resources/fxml/setting-view.fxml @@ -12,19 +12,19 @@ - + - + - - - + + + - - - - + + + +