Files
WQ_GUI/src/gui/styles.py
DXC c5a82ec342 refactor(gui/sidebar): 重组导航为四模块 + 扁平无框蓝色高亮主题 + 中括号移除
数据层(panel_registry.py):13 个 step 从「阶段一/二/三/四」重组为四个模块

  模块一 影像预处理(step 1-3)

  模块二 特征工程与数据(step 4-7)

  模块三 模型训练与反演(step 8-10)

  模块四 制图与成果汇编(step 11-13)

step_id 顺序、tab_index、面板绑定、Tab 路由全部保持零变化

文本层(water_quality_gui.py / v2):移除 └─ 字符前缀

样式层(styles.py:get_sidebar_stylesheet):扁平无框 + 蓝色高亮主题

  - 容器 QListWidget 无框化(border: none / outline: none / 透明背景)

  - 步骤项 padding 8px 6px + margin 2px 8px + border-radius 4px

  - hover 极浅蓝灰 #F0F4F8;selected 饱和蓝 #0078D4 + 白字 #FFFFFF

  - 分类头(stage_header):!enabled 选择器锁定 → 蓝色 #0078D4 + 加粗 + 上下间距

Python 代码侧:stage_item.setForeground 硬编码 #0078D4、stage_font.setBold(True)

作为 QSS 失效兜底 + 代码意图自解释

末尾迭代:四个模块名移除 [ ] 中括号(极简风)
2026-06-23 16:50:30 +08:00

609 lines
20 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
现代化样式表和主题管理模块
Modern Stylesheet and Theme Management Module
"""
class ModernStylesheet:
"""现代化样式表集合"""
# 颜色定义
COLORS = {
'main_bg': '#F0F0F0', # 主窗口背景:浅灰
'panel_bg': '#FFFFFF', # 面板/容器背景:白色
'text_primary': '#000000', # 主文字:黑色
'text_secondary': '#666666', # 辅助文字:灰色
'border': '#D0D0D0', # 边框:浅灰
'border_light': '#E8E8E8', # 浅边框
'accent': '#007BFF', # 强调色:蓝色
'success': '#28A745', # 成功绿
'error': '#DC3545', # 错误红
'warning': '#FFC107', # 警告黄
'hover': '#E8E8E8', # 悬停背景
'selected': '#0056B3', # 选中色
}
@staticmethod
def get_main_stylesheet():
"""获取主样式表"""
return f"""
/* 主窗口 */
QMainWindow {{
background-color: {ModernStylesheet.COLORS['main_bg']};
}}
/* 中央部件和容器 */
QWidget {{
background-color: {ModernStylesheet.COLORS['main_bg']};
color: {ModernStylesheet.COLORS['text_primary']};
}}
/* 分组框 */
QGroupBox {{
background-color: {ModernStylesheet.COLORS['panel_bg']};
color: {ModernStylesheet.COLORS['text_primary']};
font-weight: bold;
border: 0px;
margin-top: 10px;
padding-top: 15px;
padding-left: 9px;
padding-right: 9px;
padding-bottom: 9px;
border-bottom: 1px solid {ModernStylesheet.COLORS['border_light']};
}}
QGroupBox::title {{
subcontrol-origin: margin;
subcontrol-position: top left;
padding: 0 5px;
font-size: 12px;
font-weight: bold;
color: {ModernStylesheet.COLORS['text_primary']};
}}
/* 按钮 */
QPushButton {{
background-color: {ModernStylesheet.COLORS['panel_bg']};
color: {ModernStylesheet.COLORS['text_primary']};
border: 1px solid {ModernStylesheet.COLORS['border']};
border-radius: 7px;
padding: 3px 5px;
min-height: 25px;
max-height: 33px;
font-size: 12px;
font-weight: normal;
outline: none;
}}
QPushButton:hover {{
background-color: {ModernStylesheet.COLORS['hover']};
border: 1px solid {ModernStylesheet.COLORS['border']};
}}
QPushButton:pressed {{
background-color: {ModernStylesheet.COLORS['border_light']};
}}
QPushButton:disabled {{
background-color: {ModernStylesheet.COLORS['hover']};
color: {ModernStylesheet.COLORS['text_secondary']};
border: 1px solid {ModernStylesheet.COLORS['border_light']};
}}
QPushButton:focus {{
outline: none;
}}
/* 输入框 */
QLineEdit {{
background-color: {ModernStylesheet.COLORS['panel_bg']};
color: {ModernStylesheet.COLORS['text_primary']};
border: 1px solid {ModernStylesheet.COLORS['border']};
border-radius: 10px;
padding: 5px 8px;
min-height: 20px;
selection-background-color: {ModernStylesheet.COLORS['selected']};
selection-color: white;
}}
QLineEdit:focus {{
border: 1px solid {ModernStylesheet.COLORS['accent']};
background-color: {ModernStylesheet.COLORS['panel_bg']};
}}
/* 下拉框 */
QComboBox {{
background-color: {ModernStylesheet.COLORS['panel_bg']};
color: {ModernStylesheet.COLORS['text_primary']};
border: 1px solid {ModernStylesheet.COLORS['border']};
border-radius: 5px;
padding: 5px 8px;
min-height: 25px;
selection-background-color: {ModernStylesheet.COLORS['selected']};
}}
QComboBox:focus {{
border: 1px solid {ModernStylesheet.COLORS['accent']};
}}
QComboBox::drop-down {{
border: 0px;
padding-right: 5px;
}}
QComboBox QAbstractItemView {{
background-color: {ModernStylesheet.COLORS['panel_bg']};
color: {ModernStylesheet.COLORS['text_primary']};
selection-background-color: {ModernStylesheet.COLORS['selected']};
selection-color: white;
border: 1px solid {ModernStylesheet.COLORS['border']};
}}
/* 数值输入框 */
QSpinBox, QDoubleSpinBox {{
background-color: {ModernStylesheet.COLORS['panel_bg']};
color: {ModernStylesheet.COLORS['text_primary']};
border: 1px solid {ModernStylesheet.COLORS['border']};
border-radius: 5px;
padding: 5px 8px;
min-height: 25px;
}}
QSpinBox:focus, QDoubleSpinBox:focus {{
border: 1px solid {ModernStylesheet.COLORS['accent']};
}}
QSpinBox::up-button, QDoubleSpinBox::up-button {{
border: 0px;
padding-right: 5px;
}}
QSpinBox::down-button, QDoubleSpinBox::down-button {{
border: 0px;
padding-right: 5px;
}}
/* 复选框 */
QCheckBox {{
color: {ModernStylesheet.COLORS['text_primary']};
spacing: 5px;
}}
QCheckBox::indicator {{
width: 16px;
height: 16px;
border: 1px solid {ModernStylesheet.COLORS['border']};
border-radius: 3px;
background-color: {ModernStylesheet.COLORS['panel_bg']};
}}
QCheckBox::indicator:checked {{
background-color: {ModernStylesheet.COLORS['accent']};
border: 1px solid {ModernStylesheet.COLORS['accent']};
}}
/* 单选框 */
QRadioButton {{
color: {ModernStylesheet.COLORS['text_primary']};
spacing: 5px;
}}
QRadioButton::indicator {{
width: 16px;
height: 16px;
border: 1px solid {ModernStylesheet.COLORS['border']};
border-radius: 8px;
background-color: {ModernStylesheet.COLORS['panel_bg']};
}}
QRadioButton::indicator:checked {{
background: qradial(circle, {ModernStylesheet.COLORS['accent']} 0%, {ModernStylesheet.COLORS['accent']} 40%, {ModernStylesheet.COLORS['panel_bg']} 60%);
border: 1px solid {ModernStylesheet.COLORS['accent']};
}}
/* 文本编辑框 */
QTextEdit {{
background-color: {ModernStylesheet.COLORS['panel_bg']};
color: {ModernStylesheet.COLORS['text_primary']};
border: 1px solid {ModernStylesheet.COLORS['border']};
border-radius: 5px;
padding: 5px;
selection-background-color: {ModernStylesheet.COLORS['selected']};
selection-color: white;
}}
QTextEdit:focus {{
border: 1px solid {ModernStylesheet.COLORS['accent']};
}}
/* 列表部件 */
QListWidget {{
background-color: {ModernStylesheet.COLORS['panel_bg']};
color: {ModernStylesheet.COLORS['text_primary']};
border: 1px solid {ModernStylesheet.COLORS['border']};
border-radius: 5px;
outline: none;
}}
QListWidget::item {{
padding: 6px;
border: 0px;
}}
QListWidget::item:hover {{
background-color: {ModernStylesheet.COLORS['hover']};
}}
QListWidget::item:selected {{
background-color: {ModernStylesheet.COLORS['selected']};
color: white;
}}
/* 滚动区域 */
QScrollArea {{
background-color: {ModernStylesheet.COLORS['main_bg']};
border: 0px;
}}
/* 滚动条 */
QScrollBar:vertical {{
background-color: {ModernStylesheet.COLORS['main_bg']};
width: 12px;
border: 0px;
}}
QScrollBar::handle:vertical {{
background-color: {ModernStylesheet.COLORS['border']};
border-radius: 6px;
min-height: 20px;
}}
QScrollBar::handle:vertical:hover {{
background-color: {ModernStylesheet.COLORS['text_secondary']};
}}
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {{
border: 0px;
background-color: transparent;
}}
QScrollBar:horizontal {{
background-color: {ModernStylesheet.COLORS['main_bg']};
height: 12px;
border: 0px;
}}
QScrollBar::handle:horizontal {{
background-color: {ModernStylesheet.COLORS['border']};
border-radius: 6px;
min-width: 20px;
}}
QScrollBar::handle:horizontal:hover {{
background-color: {ModernStylesheet.COLORS['text_secondary']};
}}
QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {{
border: 0px;
background-color: transparent;
}}
/* 进度条 */
QProgressBar {{
background-color: {ModernStylesheet.COLORS['panel_bg']};
color: {ModernStylesheet.COLORS['text_primary']};
border: 1px solid {ModernStylesheet.COLORS['border']};
border-radius: 5px;
padding: 2px;
text-align: center;
height: 20px;
}}
QProgressBar::chunk {{
background-color: {ModernStylesheet.COLORS['success']};
border-radius: 3px;
}}
/* 标签 */
QLabel {{
color: {ModernStylesheet.COLORS['text_primary']};
background-color: transparent;
}}
/* 标签栏 */
QTabBar::tab {{
background-color: {ModernStylesheet.COLORS['main_bg']};
color: {ModernStylesheet.COLORS['text_primary']};
border: 1px solid {ModernStylesheet.COLORS['border']};
border-bottom: 0px;
padding: 8px 12px;
margin-right: 2px;
border-radius: 5px 5px 0px 0px;
}}
QTabBar::tab:selected {{
background-color: {ModernStylesheet.COLORS['panel_bg']};
border: 1px solid {ModernStylesheet.COLORS['border']};
border-bottom: 2px solid {ModernStylesheet.COLORS['accent']};
color: {ModernStylesheet.COLORS['accent']};
}}
QTabBar::tab:hover {{
background-color: {ModernStylesheet.COLORS['hover']};
}}
QTabWidget::pane {{
background-color: {ModernStylesheet.COLORS['panel_bg']};
border: 1px solid {ModernStylesheet.COLORS['border']};
border-top: 0px;
border-radius: 0px 0px 5px 5px;
}}
/* 菜单栏 */
QMenuBar {{
background-color: {ModernStylesheet.COLORS['panel_bg']};
color: {ModernStylesheet.COLORS['text_primary']};
border-bottom: 1px solid {ModernStylesheet.COLORS['border_light']};
padding: 2px;
}}
QMenuBar::item:selected {{
background-color: {ModernStylesheet.COLORS['hover']};
}}
/* 菜单 */
QMenu {{
background-color: {ModernStylesheet.COLORS['panel_bg']};
color: {ModernStylesheet.COLORS['text_primary']};
border: 1px solid {ModernStylesheet.COLORS['border']};
padding: 4px 0px;
border-radius: 5px;
}}
QMenu::item:selected {{
background-color: {ModernStylesheet.COLORS['hover']};
padding-left: 20px;
}}
QMenu::separator {{
height: 1px;
background-color: {ModernStylesheet.COLORS['border_light']};
margin: 4px 0px;
}}
/* 状态栏 */
QStatusBar {{
background-color: {ModernStylesheet.COLORS['panel_bg']};
color: {ModernStylesheet.COLORS['text_primary']};
border-top: 1px solid {ModernStylesheet.COLORS['border_light']};
}}
/* 框架 */
QFrame {{
background-color: {ModernStylesheet.COLORS['main_bg']};
border: 0px;
}}
/* 对话框 */
QDialog {{
background-color: {ModernStylesheet.COLORS['main_bg']};
}}
/* 消息框 */
QMessageBox {{
background-color: {ModernStylesheet.COLORS['main_bg']};
}}
QMessageBox QLabel {{
color: {ModernStylesheet.COLORS['text_primary']};
}}
"""
@staticmethod
def get_button_stylesheet(style_type='normal'):
"""获取特定样式的按钮样式表"""
colors = ModernStylesheet.COLORS
if style_type == 'primary':
# 蓝色主按钮
return f"""
QPushButton {{
background-color: {colors['accent']};
color: white;
border: 1px solid {colors['accent']};
border-radius: 7px;
padding: 3px 5px;
min-height: 25px;
max-height: 33px;
font-weight: bold;
}}
QPushButton:hover {{
background-color: #0056b3;
border: 1px solid #0056b3;
}}
QPushButton:pressed {{
background-color: #003d82;
}}
QPushButton:disabled {{
background-color: {colors['hover']};
color: {colors['text_secondary']};
border: 1px solid {colors['border_light']};
}}
"""
elif style_type == 'success':
# 绿色成功按钮
return f"""
QPushButton {{
background-color: {colors['success']};
color: white;
border: 1px solid {colors['success']};
border-radius: 7px;
padding: 3px 5px;
min-height: 25px;
max-height: 33px;
font-weight: bold;
}}
QPushButton:hover {{
background-color: #218838;
border: 1px solid #218838;
}}
QPushButton:pressed {{
background-color: #1a6c28;
}}
QPushButton:disabled {{
background-color: {colors['hover']};
color: {colors['text_secondary']};
border: 1px solid {colors['border_light']};
}}
"""
elif style_type == 'danger':
# 红色危险按钮
return f"""
QPushButton {{
background-color: {colors['error']};
color: white;
border: 1px solid {colors['error']};
border-radius: 7px;
padding: 3px 5px;
min-height: 25px;
max-height: 33px;
font-weight: bold;
}}
QPushButton:hover {{
background-color: #c82333;
border: 1px solid #c82333;
}}
QPushButton:pressed {{
background-color: #9a1a24;
}}
QPushButton:disabled {{
background-color: {colors['hover']};
color: {colors['text_secondary']};
border: 1px solid {colors['border_light']};
}}
"""
else: # normal/default
return f"""
QPushButton {{
background-color: {colors['panel_bg']};
color: {colors['text_primary']};
border: 1px solid {colors['border']};
border-radius: 7px;
padding: 3px 5px;
min-height: 25px;
max-height: 33px;
}}
QPushButton:hover {{
background-color: {colors['hover']};
border: 1px solid {colors['border']};
}}
QPushButton:pressed {{
background-color: {colors['border_light']};
}}
QPushButton:disabled {{
background-color: {colors['hover']};
color: {colors['text_secondary']};
border: 1px solid {colors['border_light']};
}}
"""
@staticmethod
def get_toolbar_stylesheet():
"""获取顶部工具栏样式表"""
colors = ModernStylesheet.COLORS
return f"""
QWidget {{
background-color: {colors['panel_bg']};
border-bottom: 1px solid {colors['border_light']};
}}
QLabel {{
color: {colors['text_primary']};
}}
QPushButton {{
background-color: {colors['panel_bg']};
color: {colors['text_primary']};
border: 1px solid {colors['border']};
border-radius: 5px;
padding: 5px 10px;
min-height: 25px;
}}
QPushButton:hover {{
background-color: {colors['hover']};
}}
"""
@staticmethod
def get_sidebar_stylesheet():
"""获取左侧边栏样式表
设计主题:扁平无框 + 蓝色高亮。
结构契约:
- 分类头 stage_header 项已通过 setFlags(~Qt.ItemIsEnabled) 禁用,
因此 :!enabled 选择器可精确锁定分类头(蓝色加粗)。
- 可点击的步骤项保持 enabled进入 :enabled 通道
padding/margin 留白 + 圆角 + hover/selected 蓝色现代感)。
"""
colors = ModernStylesheet.COLORS
# 主题色板(蓝色高亮)
stage_header_color = '#0078D4' # 分类头:亮蓝色加粗
step_hover_bg = '#F0F4F8' # hover极浅蓝灰
step_selected_bg = '#0078D4' # selected饱和蓝
step_selected_fg = '#FFFFFF' # selected白字
return f"""
QWidget {{
background-color: {colors['panel_bg']};
border-right: 1px solid {colors['border_light']};
}}
QLabel {{
color: {colors['text_primary']};
font-weight: bold;
}}
/* ── 容器:无框化、零描边、零焦点环 ── */
QListWidget {{
border: none;
outline: none;
background-color: transparent;
}}
/* ── 分类头stage_header禁用态亮蓝色 + 加粗 + 上下间距 ── */
QListWidget::item:!enabled {{
color: {stage_header_color};
font-weight: bold;
background-color: transparent;
border: none;
padding: 14px 8px 6px 8px;
margin-top: 4px;
}}
/* ── 步骤项enabledpadding/margin 留白 + 圆角过渡 ── */
QListWidget::item:enabled {{
color: {colors['text_secondary']};
padding: 8px 6px;
margin: 2px 8px;
border: none;
border-radius: 4px;
}}
/* ── 步骤项 hover未选中态极浅蓝灰悬浮 ── */
QListWidget::item:enabled:hover:!selected {{
background-color: {step_hover_bg};
color: {colors['text_primary']};
}}
/* ── 步骤项 selected饱和蓝高亮 + 白字 ── */
QListWidget::item:enabled:selected {{
background-color: {step_selected_bg};
color: {step_selected_fg};
border: none;
font-weight: bold;
}}
/* ── 分隔符占位项:完全透明,零干扰 ── */
QListWidget::item[separator="true"] {{
background-color: transparent;
border: none;
padding: 0px;
margin: 0px;
min-height: 4px;
}}
"""