界面优化

This commit is contained in:
DXC
2026-05-07 16:49:24 +08:00
parent a645c64987
commit 742bc392a5
14 changed files with 590 additions and 86 deletions

View File

@ -1475,7 +1475,7 @@ class WaterQualityGUI(QMainWindow):
def init_ui(self):
"""初始化UI"""
self.setWindowTitle("水质参数反演分析系统 v1.0")
self.setWindowTitle("水质参数反演分析系统 v1.1")
# 获取屏幕可用区域(排除任务栏)
screen_geometry = QApplication.primaryScreen().availableGeometry()
@ -1658,48 +1658,66 @@ class WaterQualityGUI(QMainWindow):
def create_banner_widget(self):
"""创建横幅区域 - 支持自适应等比缩放"""
# 横幅标题文字(方便后续直接修改版本号)
self._APP_TITLE = "Mega Water V1.1"
# 创建横幅容器
banner_widget = QWidget()
banner_layout = QHBoxLayout()
banner_layout.setContentsMargins(0, 0, 0, 0)
banner_layout.setSpacing(0)
# 不设置居中对齐,让横幅填满整个容器
# 创建横幅标签 - 完全跟随窗口等比缩放,填满整个区域
# ===== 底图层 =====
self.banner_label = QLabel()
# 最小高度保证:当窗口很小时至少显示 38px 高 (200px 宽 / 5.25)
self.banner_label.setMinimumHeight(int(200 / 5.25)) # ≈ 38px
# 使用 Expanding 策略让标签填满可用空间
self.banner_label.setMinimumHeight(140)
self.banner_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.banner_label.setScaledContents(False)
# 清除 QLabel 默认的 margin 和 padding消除右侧空白
self.banner_label.setStyleSheet("margin: 0px; padding: 0px; border: none;")
# 保存原始pixmap用于后续缩放
# 强制 banner_widget 展开填充 toolbar 全部宽度(清除 addWidget 的默认居中行为)
banner_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
banner_widget.setMinimumWidth(0) # 确保可以被 layout 压缩/扩展到任意宽度
banner_widget.setStyleSheet("margin: 0px; padding: 0px; border: none;")
# 纯净底图路径(无水印文字)
if hasattr(sys, '_MEIPASS'):
banner_path = os.path.join(sys._MEIPASS, 'data', 'icons', 'Mega Water 1.0.png')
banner_path = os.path.join(sys._MEIPASS, 'data', 'icons', 'Mega Water 1.0.jpg')
else:
banner_path = str(Path(__file__).parent.parent.parent / "data" / "icons" / "Mega Water 1.0.png")
banner_path = str(Path(__file__).parent.parent.parent / "data" / "icons" / "Mega Water 1.0.jpg")
self.banner_pixmap = QPixmap(banner_path)
if not self.banner_pixmap.isNull():
# 延迟执行,确保窗口已初始化
QTimer.singleShot(50, self.update_banner_image)
else:
# 如果图片加载失败,显示占位符
self.banner_label.setText("水质参数反演分析系统")
self.banner_label.setText("背景图加载失败")
self.banner_label.setStyleSheet("""
QLabel {
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #0078d4, stop:1 #00a0e9);
color: white;
font-size: 26px;
font-weight: bold;
color: white; font-size: 26px; font-weight: bold;
border-bottom: 3px solid #005a9e;
}
""")
banner_layout.addWidget(self.banner_label)
# ===== 文字叠加层 =====
# 注意这里:第二个参数改成了 self.banner_label直接附着在底图上
self.banner_title_label = QLabel(self._APP_TITLE, self.banner_label)
self.banner_title_label.setStyleSheet("""
QLabel {
background: transparent;
color: white;
font-size: 48px; /* 显著增大字号 */
font-weight: normal; /* 取消粗体,还原原图的优雅感 */
font-family: "Times New Roman", "Georgia", "STZhongsong", serif; /* 衬线字体家族 */
letter-spacing: 1px;
}
""")
self.banner_title_label.setAttribute(Qt.WA_TransparentForMouseEvents) # 鼠标穿透
self.banner_title_label.show() # 第一道保险:强制现身
self.banner_title_label.raise_() # 第二道保险:强制图层置顶
banner_widget.setLayout(banner_layout)
# 将横幅添加到窗口顶部(在标题栏下方)
@ -1721,6 +1739,10 @@ class WaterQualityGUI(QMainWindow):
margin: 0px;
padding: 0px;
}
QToolBar > QWidget {
margin: 0px;
padding: 0px;
}
""")
self.addToolBar(Qt.TopToolBarArea, banner_toolbar)
@ -2122,10 +2144,34 @@ class WaterQualityGUI(QMainWindow):
elif index == 6:
self.step6_panel.update_from_config(work_dir=self.work_dir, pipeline=self.pipeline)
# Step6.5(非经验回归建模)切换时自动填充训练数据和模型目录
elif index == 7:
self.step6_5_panel.update_from_config(work_dir=self.work_dir, pipeline=self.pipeline)
# Step6.75(自定义回归建模)切换时自动填充训练数据和模型目录
elif index == 8:
self.step6_75_panel.update_from_config(work_dir=self.work_dir, pipeline=self.pipeline)
# Step7采样点布设切换时自动填充掩膜和输出路径
elif index == 9:
self.step7_panel.update_from_config(work_dir=self.work_dir, pipeline=self.pipeline)
# Step8机器学习预测切换时自动填充采样光谱和模型目录
elif index == 10:
self.step8_panel.update_from_config(work_dir=self.work_dir, pipeline=self.pipeline)
# Step8.5(非经验模型预测)切换时自动填充采样光谱和回归模型目录
elif index == 11:
self.step8_5_panel.update_from_config(work_dir=self.work_dir, pipeline=self.pipeline)
# Step8.75(自定义回归预测)切换时自动填充采样光谱和自定义回归模型目录
elif index == 12:
self.step8_75_panel.update_from_config(work_dir=self.work_dir, pipeline=self.pipeline)
# Step9专题图生成切换时自动填充预测结果目录
elif index == 13:
self.step9_panel.update_from_config(work_dir=self.work_dir, pipeline=self.pipeline)
# 可视化分析面板切换时自动推断图像目录并加载目录树
elif index == 14:
self.viz_panel.update_from_config(work_dir=self.work_dir, pipeline=self.pipeline)
@ -2853,36 +2899,43 @@ class WaterQualityGUI(QMainWindow):
self.training_mode_action.setText("有训练数据模式" if checked else "无训练数据模式")
def update_banner_image(self):
"""更新横幅图片 - 完全跟随窗口等比缩放,填满可用宽度"""
"""更新横幅图片 - 固定高度 + 居中裁剪(类似 CSS object-fit: cover"""
if not hasattr(self, 'banner_pixmap') or self.banner_pixmap.isNull():
return
# 获取可用宽度(考虑工具栏边距),跟随窗口实时变化
available_width = max(200, self.width() - 60)
# 先根据可用宽度计算目标高度(严格 5.25:1
target_height = int(available_width / 5.25)
# 限制最小高度
if target_height < 38:
target_height = 38
available_width = int(38 * 5.25)
TARGET_HEIGHT = 140
target_width = self.width()
# 计算图片目标尺寸(保持 5.25:1 比例)
target_width = available_width
# 设置固定尺寸,确保标签严格填满整个区域
self.banner_label.setFixedSize(target_width, target_height)
# 手动计算 Cover 缩放比例:取宽/高各自所需比例的最大值,
# 确保缩放后图片的宽 ≥ target_width 且高 ≥ TARGET_HEIGHT
orig_w = self.banner_pixmap.width()
orig_h = self.banner_pixmap.height()
scale_factor = max(target_width / orig_w, TARGET_HEIGHT / orig_h)
new_w = int(orig_w * scale_factor)
new_h = int(orig_h * scale_factor)
# 等比缩放到目标尺寸,填满整个区域(允许轻微裁剪)
scaled_pixmap = self.banner_pixmap.scaled(
target_width,
target_height,
Qt.KeepAspectRatioByExpanding, # 保持比例,填满区域,允许裁剪超出部分
new_w, new_h,
Qt.IgnoreAspectRatio,
Qt.SmoothTransformation
)
self.banner_label.setPixmap(scaled_pixmap)
# 居中裁剪,截取中间核心区域
crop_x = (new_w - target_width) // 2
crop_y = (new_h - TARGET_HEIGHT) // 2
final_pixmap = scaled_pixmap.copy(crop_x, crop_y, target_width, TARGET_HEIGHT)
self.banner_label.setFixedHeight(TARGET_HEIGHT)
self.banner_label.setFixedWidth(target_width) # 强制宽度填满容器
self.banner_label.setPixmap(final_pixmap)
self.banner_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
# 文字叠加层:绝对定位,保持垂直居中
if hasattr(self, 'banner_title_label'):
title_x = 160
title_y = max(0, (TARGET_HEIGHT - 60) // 2)
self.banner_title_label.move(title_x, title_y)
self.banner_title_label.resize(target_width - title_x - 20, 60)
def resizeEvent(self, event):
"""窗口大小改变事件 - 实时更新横幅图片等比缩放"""