This commit is contained in:
叁玖领域 2025-10-09 13:01:38 +08:00
parent 81b420bacb
commit 0f54983b30
12 changed files with 711 additions and 40 deletions

View File

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ASMIdeaPluginConfiguration">
<asm skipDebug="false" skipFrames="false" skipCode="false" expandFrames="false" />

View File

@ -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

View File

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

View File

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

View File

@ -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<ButtonType> 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);
}
}

View File

@ -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) {

View File

@ -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反馈明显 */
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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增加与下方取消/保存按钮的距离 */
}

View File

@ -12,7 +12,7 @@
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="1000.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="top.r3944realms.docchecktoolrefactored.ui.MainStageController">
<VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="1000.0" prefWidth="1200.0" stylesheets="@../css/main.css" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="top.r3944realms.docchecktoolrefactored.ui.MainStageController">
<children>
<MenuBar prefWidth="2558.0" VBox.vgrow="ALWAYS">
<menus>
@ -27,7 +27,7 @@
</Menu>
<Menu fx:id="helpM" mnemonicParsing="false" text="帮助">
<items>
<MenuItem fx:id="helpDocMI" mnemonicParsing="false" onAction="#onOpenHelpDoc" text="帮助文档" />
<MenuItem fx:id="helpDocMI" mnemonicParsing="false" onAction="#onOpenHelpDoc" text="用户使用说明书" />
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem fx:id="aboutSoftwareMI" mnemonicParsing="false" onAction="#onAbout" text="关于软件" />
</items>

View File

@ -12,19 +12,19 @@
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<VBox xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="top.r3944realms.docchecktoolrefactored.ui.SettingDialogController">
<VBox stylesheets="@../css/setting.css" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="top.r3944realms.docchecktoolrefactored.ui.SettingDialogController">
<children>
<GridPane>
<GridPane VBox.vgrow="ALWAYS">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="138.0" minWidth="10.0" prefWidth="133.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="109.0" minWidth="10.0" prefWidth="94.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="95.0" minWidth="10.0" prefWidth="73.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="192.0" minWidth="10.0" prefWidth="147.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="131.0" minWidth="10.0" prefWidth="119.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="95.0" minWidth="10.0" prefWidth="34.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="ALWAYS" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="ALWAYS" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="ALWAYS" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="ALWAYS" />
</rowConstraints>
<children>
<Label text="步骤扫描超时时间:" GridPane.rowIndex="1">
@ -37,7 +37,7 @@
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</GridPane.margin>
</Spinner>
<Label prefWidth="114.0" text="步骤任务超时时间:" GridPane.rowIndex="2">
<Label prefHeight="19.0" prefWidth="167.0" text="步骤任务超时时间:" GridPane.rowIndex="2">
<GridPane.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</GridPane.margin>