界面优化
This commit is contained in:
@ -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):
|
||||
"""窗口大小改变事件 - 实时更新横幅图片等比缩放"""
|
||||
|
||||
Reference in New Issue
Block a user