QT 设置固定宽度、高度、大小

本文介绍了在Qt编程中,如何使用m_pListW对象进行界面控件的尺寸管理,包括设置固定宽度、高度,以及设定最大最小尺寸的方法,如setFixedWidth(200)、setFixedHeight()、setFixedSize()和setMinimumSize()、setMaximumSize()函数的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

m_pListW->setFixedWidth(200);

设置固定高度:setFixedHeight();

设置固定大小:setFixedSize();

设置最大最小:setMinimumSize()、setMaximumSize()

import sys import json import os from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QListWidget, QLabel, QDialog, QLineEdit, QTextEdit, QComboBox, QMessageBox, QTabWidget, QToolBar, QAction, QTreeWidget, QTreeWidgetItem, QSplitter, QStatusBar, QToolButton, QStackedWidget, QDateEdit, QListWidgetItem, QCheckBox, QFormLayout) from PyQt5.QtCore import Qt, QSize, QDate from PyQt5.QtGui import QIcon, QFont, QColor, QPalette, QBrush, QLinearGradient class WorkflowManager(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("高级工作流程管理器 - 专业版") self.resize(1200, 800) self.workflows = [] self.current_workflow = None self.current_stage_index = 0 self.load_workflows() # 设置主窗口样式 - 现代专业配色方案 self.setStyleSheet(""" QMainWindow { background-color: #f8f9fa; font-family: 'Segoe UI', 'Arial', sans-serif; } QToolBar { background-color: #ffffff; border-bottom: 1px solid #e9ecef; padding: 5px; spacing: 10px; } QPushButton { background-color: #4e73df; color: white; border-radius: 6px; padding: 8px 16px; min-width: 90px; font-size: 14px; font-weight: 500; border: none; transition: background-color 0.3s; } QPushButton:hover { background-color: #2e59d9; } QPushButton:pressed { background-color: #1a3bb3; } QListWidget, QTreeWidget { background-color: white; border: 1px solid #e0e0e0; border-radius: 8px; font-size: 14px; padding: 5px; } QTabWidget::pane { border: 1px solid #e0e0e0; border-radius: 8px; background: white; margin-top: 5px; } QTabBar::tab { background: #f8f9fa; border: 1px solid #e0e0e0; border-bottom: none; padding: 10px 20px; font-size: 14px; color: #495057; border-top-left-radius: 6px; border-top-right-radius: 6px; margin-right: 2px; } QTabBar::tab:selected { background: white; border-bottom-color: white; font-weight: 600; color: #4e73df; } QTabBar::tab:hover { background: #e9ecef; } QLabel { font-size: 14px; color: #495057; } QLineEdit, QTextEdit, QComboBox { font-size: 14px; padding: 8px; background-color: white; color: #495057; border: 1px solid #ced4da; border-radius: 4px; } QLineEdit:focus, QTextEdit:focus { border: 1px solid #4e73df; } QCheckBox { font-size: 14px; color: #495057; spacing: 8px; } QStatusBar { background-color: #ffffff; color: #495057; font-size: 13px; border-top: 1px solid #e9ecef; } """) # 设置应用字体 app_font = QFont("Segoe UI", 10) QApplication.setFont(app_font) # 创建主界面 self.create_main_ui() # 加载默认工作流程 if self.workflows: self.current_workflow = self.workflows[0] self.update_workflow_display() def create_main_ui(self): """创建主界面""" # 创建工具栏 toolbar = QToolBar("主工具栏") toolbar.setIconSize(QSize(24, 24)) toolbar.setMovable(False) self.addToolBar(toolbar) # 添加工具栏动作 new_workflow_action = QAction(QIcon.fromTheme("document-new"), "新建流程", self) new_workflow_action.triggered.connect(self.new_workflow) toolbar.addAction(new_workflow_action) edit_workflow_action = QAction(QIcon.fromTheme("document-edit"), "编辑流程", self) edit_workflow_action.triggered.connect(self.edit_workflow) toolbar.addAction(edit_workflow_action) delete_workflow_action = QAction(QIcon.fromTheme("edit-delete"), "删除流程", self) delete_workflow_action.triggered.connect(self.delete_workflow) toolbar.addAction(delete_workflow_action) save_action = QAction(QIcon.fromTheme("document-save"), "保存", self) save_action.triggered.connect(self.save_workflows) toolbar.addAction(save_action) toolbar.addSeparator() stats_action = QAction(QIcon.fromTheme("view-statistics"), "统计", self) stats_action.triggered.connect(self.show_stats) toolbar.addAction(stats_action) # 创建主内容区域 main_widget = QWidget() self.setCentralWidget(main_widget) main_layout = QHBoxLayout(main_widget) main_layout.setContentsMargins(15, 15, 15, 15) main_layout.setSpacing(15) # 左侧工作流程列表 left_panel = QWidget() left_panel.setFixedWidth(280) left_layout = QVBoxLayout(left_panel) left_layout.setContentsMargins(0, 0, 0, 0) workflow_label = QLabel("工作流程") workflow_label.setStyleSheet("font-size: 16px; font-weight: 600; color: #4e73df; margin-bottom: 8px;") left_layout.addWidget(workflow_label) self.workflow_list = QTreeWidget() self.workflow_list.setHeaderLabel("") self.workflow_list.setRootIsDecorated(False) self.workflow_list.itemClicked.connect(self.select_workflow) left_layout.addWidget(self.workflow_list) main_layout.addWidget(left_panel) # 右侧主内容区 right_splitter = QSplitter(Qt.Vertical) # 工作流程可视化区 self.flow_visualization = QWidget() self.flow_visualization.setStyleSheet("background-color: white; border-radius: 8px; padding: 15px;") flow_viz_layout = QVBoxLayout(self.flow_visualization) self.flow_title = QLabel() self.flow_title.setStyleSheet("font-size: 20px; font-weight: 600; color: #4e73df; margin-bottom: 15px;") flow_viz_layout.addWidget(self.flow_title) # 添加滚动区域 scroll_widget = QWidget() scroll_layout = QHBoxLayout(scroll_widget) scroll_layout.setContentsMargins(0, 0, 0, 0) self.flow_stages = QHBoxLayout() self.flow_stages.setSpacing(15) scroll_layout.addLayout(self.flow_stages) flow_viz_layout.addWidget(scroll_widget) # 添加流程控制按钮 self.flow_control = QHBoxLayout() self.flow_control.setAlignment(Qt.AlignCenter) self.flow_control.setSpacing(20) self.prev_stage_btn = QPushButton("◀ 上一阶段") self.prev_stage_btn.setIcon(QIcon.fromTheme("go-previous")) self.prev_stage_btn.setStyleSheet("min-width: 120px;") self.prev_stage_btn.clicked.connect(self.prev_stage) self.next_stage_btn = QPushButton("下一阶段 ▶") self.next_stage_btn.setIcon(QIcon.fromTheme("go-next")) self.next_stage_btn.setStyleSheet("min-width: 120px;") self.next_stage_btn.clicked.connect(self.next_stage) self.flow_control.addWidget(self.prev_stage_btn) self.flow_control.addWidget(self.next_stage_btn) flow_viz_layout.addLayout(self.flow_control) right_splitter.addWidget(self.flow_visualization) # 成果物管理区 self.artifacts_management = QTabWidget() self.artifacts_management.setStyleSheet(""" QTabWidget::pane { border: none; } """) # 成果物检查 self.artifacts_check = QWidget() self.artifacts_check.setStyleSheet("background-color: white; border-radius: 8px; padding: 15px;") artifacts_layout = QVBoxLayout(self.artifacts_check) self.artifacts_label = QLabel("成果物检查") self.artifacts_label.setStyleSheet("font-size: 18px; font-weight: 600; color: #4e73df; margin-bottom: 10px;") artifacts_layout.addWidget(self.artifacts_label) self.artifacts_list = QListWidget() self.artifacts_list.setStyleSheet("border-radius: 6px;") artifacts_layout.addWidget(self.artifacts_list) # 成果物状态说明 self.status_info = QLabel("") self.status_info.setStyleSheet(""" font-size: 14px; font-weight: 500; color: #6c757d; background-color: #f8f9fa; padding: 10px; border-radius: 6px; margin-top: 10px; """) artifacts_layout.addWidget(self.status_info) self.artifacts_management.addTab(self.artifacts_check, "成果物检查") # 统计 self.stats_widget = QWidget() self.stats_widget.setStyleSheet("background-color: white; border-radius: 8px; padding: 15px;") stats_layout = QVBoxLayout(self.stats_widget) self.stats_label = QLabel("工作流程统计信息将显示在这里") self.stats_label.setStyleSheet("font-size: 14px;") stats_layout.addWidget(self.stats_label) self.artifacts_management.addTab(self.stats_widget, "统计") right_splitter.addWidget(self.artifacts_management) main_layout.addWidget(right_splitter, 1) # 状态栏 self.status_bar = QStatusBar() self.setStatusBar(self.status_bar) self.status_bar.showMessage("就绪") def load_workflows(self): """加载工作流程""" if os.path.exists("workflows.json"): with open("workflows.json", "r") as f: self.workflows = json.load(f) else: # 创建默认工作流程 - 使用更协调的颜色方案 default_workflow = { "name": "软件开发变更流程", "description": "标准的软件开发变更管理流程", "stages": [ {"name": "变更点分析", "description": "分析客户提供的变更需求", "color": "#4e73df", "artifacts": ["需求分析文档"], "completed": False}, {"name": "变更点差分", "description": "识别变更前后的差异", "color": "#1cc88a", "artifacts": ["差异分析报告"], "completed": False}, {"name": "设计书修改", "description": "更新设计文档", "color": "#36b9cc", "artifacts": ["更新后的设计文档"], "completed": False}, {"name": "代码修改", "description": "实施代码变更", "color": "#f6c23e", "artifacts": ["变更后的代码"], "completed": False}, {"name": "代码验证", "description": "测试变更代码", "color": "#e74a3b", "artifacts": ["测试报告"], "completed": False}, {"name": "代码审核", "description": "进行代码审查", "color": "#6f42c1", "artifacts": ["代码审查意见"], "completed": False}, {"name": "代码集成", "description": "合并到主分支", "color": "#fd7e14", "artifacts": ["集成后的代码"], "completed": False}, {"name": "成果物输出", "description": "生成最终交付物", "color": "#20c997", "artifacts": ["最终交付包"], "completed": False} ], "tasks": [] } self.workflows.append(default_workflow) self.save_workflows() def save_workflows(self): """保存工作流程""" with open("workflows.json", "w") as f: json.dump(self.workflows, f, indent=4) self.status_bar.showMessage("工作流程已保存", 3000) def update_workflow_display(self): """更新工作流程显示""" if not self.current_workflow: return # 更新工作流程列表 self.workflow_list.clear() for workflow in self.workflows: item = QTreeWidgetItem(self.workflow_list) item.setText(0, workflow["name"]) item.setFont(0, QFont("Segoe UI", 11)) item.setData(0, Qt.UserRole, workflow) # 高亮显示当前选中的工作流程 if workflow == self.current_workflow: item.setBackground(0, QColor("#e9ecef")) # 更新流程标题 self.flow_title.setText(f"{self.current_workflow['name']} - {self.current_workflow['description']}") # 更新流程阶段显示 self.clear_flow_stages() for i, stage in enumerate(self.current_workflow["stages"]): stage_widget = self.create_stage_widget(stage, i) self.flow_stages.addWidget(stage_widget) # 更新按钮状态 self.update_buttons_state() def clear_flow_stages(self): """清空流程阶段显示""" while self.flow_stages.count(): item = self.flow_stages.takeAt(0) if item.widget(): item.widget().deleteLater() def create_stage_widget(self, stage, index): """创建单个阶段显示组件""" stage_widget = QWidget() stage_widget.setFixedWidth(200) # 根据阶段状态设置样式 if index == self.current_stage_index: # 当前阶段 - 高亮显示 stage_widget.setStyleSheet(f""" QWidget {{ background-color: {stage['color']}20; border: 2px solid {stage['color']}; border-radius: 10px; padding: 15px; }} QLabel {{ color: {stage['color']}; }} """) elif index < self.current_stage_index: # 已完成阶段 - 灰色显示 stage_widget.setStyleSheet(f""" QWidget {{ background-color: #e9ecef; border: 2px solid #ced4da; border-radius: 10px; padding: 15px; }} QLabel {{ color: #6c757d; }} """) else: # 未开始阶段 - 默认样式 stage_widget.setStyleSheet(f""" QWidget {{ background-color: #f8f9fa; border: 2px solid #e9ecef; border-radius: 10px; padding: 15px; }} QLabel {{ color: #6c757d; }} """) layout = QVBoxLayout(stage_widget) layout.setSpacing(8) title = QLabel(stage["name"]) title.setStyleSheet("font-weight: 600; font-size: 16px;") layout.addWidget(title) desc = QLabel(stage["description"]) desc.setWordWrap(True) desc.setStyleSheet("font-size: 13px;") layout.addWidget(desc) # 显示阶段状态 status_text = "已完成" if stage.get("completed", False) else "进行中" if index == self.current_stage_index else "未开始" status = QLabel(f"状态: {status_text}") status.setStyleSheet("font-size: 12px; font-style: italic; margin-top: 8px;") layout.addWidget(status) # 添加阶段选择按钮 select_btn = QPushButton("选择此阶段") select_btn.setStyleSheet(f""" QPushButton {{ background-color: {stage['color']}; color: white; font-weight: 500; margin-top: 10px; }} QPushButton:hover {{ background-color: {self.darken_color(stage['color'], 20)}; }} """) select_btn.clicked.connect(lambda _, i=index: self.select_stage(i)) layout.addWidget(select_btn) return stage_widget def darken_color(self, hex_color, percent): """使颜色变暗指定百分比""" r = int(int(hex_color[1:3], 16) * (100 - percent) / 100) g = int(int(hex_color[3:5], 16) * (100 - percent) / 100) b = int(int(hex_color[5:7], 16) * (100 - percent) / 100) return f"#{max(0, min(255, r)):02x}{max(0, min(255, g)):02x}{max(0, min(255, b)):02x}" def select_workflow(self, item): """选择工作流程""" self.current_workflow = item.data(0, Qt.UserRole) self.current_stage_index = 0 self.update_workflow_display() self.update_task_display() self.update_artifacts_display() def select_stage(self, index): """选择阶段""" # 允许选择任何阶段,但会提示如果跳过未完成阶段 if index > self.current_stage_index: reply = QMessageBox.question( self, '确认跳转', '您正在跳转到未完成的阶段。确定要继续吗?', QMessageBox.Yes | QMessageBox.No ) if reply == QMessageBox.No: return self.current_stage_index = index self.update_workflow_display() self.update_task_display() self.update_artifacts_display() def prev_stage(self): """返回上一阶段""" if self.current_stage_index > 0: self.current_stage_index -= 1 self.update_workflow_display() self.update_task_display() self.update_artifacts_display() self.status_bar.showMessage(f"已返回阶段: {self.current_workflow['stages'][self.current_stage_index]['name']}", 3000) def next_stage(self): """进入下一阶段""" if self.current_stage_index < len(self.current_workflow["stages"]) - 1: # 检查当前阶段是否已完成 current_stage = self.current_workflow["stages"][self.current_stage_index] # 检查成果物是否全部完成 if not current_stage.get("completed", False): QMessageBox.warning(self, "警告", "当前阶段成果物未全部完成,无法进入下一阶段!") return self.current_stage_index += 1 self.save_workflows() self.update_workflow_display() self.update_artifacts_display() self.status_bar.showMessage(f"已进入新阶段: {self.current_workflow['stages'][self.current_stage_index]['name']}", 3000) def check_artifacts_completed(self): """检查成果物是否全部完成""" for i in range(self.artifacts_list.count()): item = self.artifacts_list.item(i) widget = self.artifacts_list.itemWidget(item) checkbox = widget.findChild(QCheckBox) if not checkbox.isChecked(): return False return True def update_buttons_state(self): """更新按钮状态""" self.prev_stage_btn.setEnabled(self.current_stage_index > 0) self.next_stage_btn.setEnabled( self.current_stage_index < len(self.current_workflow["stages"]) - 1 ) def new_workflow(self): """新建工作流程""" dialog = WorkflowDialog(self) if dialog.exec_() == QDialog.Accepted: new_workflow = dialog.get_workflow() self.workflows.append(new_workflow) self.current_workflow = new_workflow self.current_stage_index = 0 self.save_workflows() self.update_workflow_display() self.update_task_display() self.update_artifacts_display() def edit_workflow(self): """编辑工作流程""" if not self.current_workflow: return dialog = WorkflowDialog(self, self.current_workflow) if dialog.exec_() == QDialog.Accepted: edited_workflow = dialog.get_workflow() index = self.workflows.index(self.current_workflow) self.workflows[index] = edited_workflow self.current_workflow = edited_workflow self.save_workflows() self.update_workflow_display() self.update_task_display() self.update_artifacts_display() def delete_workflow(self): """删除当前工作流程""" if not self.current_workflow: QMessageBox.warning(self, "警告", "请先选择一个工作流程!") return reply = QMessageBox.question( self, '确认删除', f"确定要删除工作流程【{self.current_workflow['name']}】吗?\n此操作不可恢复!", QMessageBox.Yes | QMessageBox.No ) if reply == QMessageBox.Yes: # 从工作流程列表中移除当前工作流程 self.workflows.remove(self.current_workflow) # 更新当前选中的工作流程 if self.workflows: self.current_workflow = self.workflows[0] self.current_stage_index = 0 else: self.current_workflow = None self.current_stage_index = -1 # 保存更改并更新界面 self.save_workflows() self.update_workflow_display() self.update_task_display() self.update_artifacts_display() self.status_bar.showMessage(f"工作流程已删除", 3000) def update_task_display(self): """更新成果物显示""" self.update_artifacts_display() def update_artifacts_display(self): """更新成果物显示""" self.artifacts_list.clear() if not self.current_workflow: return current_stage = self.current_workflow["stages"][self.current_stage_index] self.artifacts_label.setText(f"成果物检查 - {current_stage['name']}") for artifact in current_stage.get("artifacts", []): item = QListWidgetItem() widget = QWidget() layout = QHBoxLayout(widget) layout.setContentsMargins(10, 5, 10, 5) checkbox = QCheckBox(artifact) checkbox.setStyleSheet("font-size: 11px;") checkbox.stateChanged.connect(self.update_stage_status) layout.addWidget(checkbox) item.setSizeHint(widget.sizeHint()) self.artifacts_list.addItem(item) self.artifacts_list.setItemWidget(item, widget) # 更新状态信息 self.update_stage_status() def update_stage_status(self): """更新阶段状态""" if not self.current_workflow: return current_stage = self.current_workflow["stages"][self.current_stage_index] total_artifacts = len(current_stage.get("artifacts", [])) completed_artifacts = 0 for i in range(self.artifacts_list.count()): item = self.artifacts_list.item(i) widget = self.artifacts_list.itemWidget(item) checkbox = widget.findChild(QCheckBox) if checkbox.isChecked(): completed_artifacts += 1 # 更新状态文本 if total_artifacts == 0: status_text = "当前阶段没有成果物" status_color = "#6c757d" elif completed_artifacts == 0: status_text = "状态: 待开始 (0% 完成)" status_color = "#e74a3b" current_stage["completed"] = False elif completed_artifacts < total_artifacts: percent = (completed_artifacts / total_artifacts) * 100 status_text = f"状态: 进行中 ({percent:.0f}% 完成)" status_color = "#f6c23e" current_stage["completed"] = False else: status_text = "状态: 已完成 (100% 完成)" status_color = "#1cc88a" current_stage["completed"] = True self.status_info.setText(status_text) self.status_info.setStyleSheet(f""" font-size: 14px; font-weight: 500; color: white; background-color: {status_color}; padding: 10px; border-radius: 6px; margin-top: 10px; """) self.update_buttons_state() def show_stats(self): """显示统计信息""" if not self.current_workflow: return stats_text = f"<h2 style='color: #4e73df;'>{self.current_workflow['name']} 统计</h2>" # 按阶段统计 stats_text += "<h3 style='color: #5a5c69;'>按阶段统计</h3><ul style='list-style-type: none; padding-left: 0;'>" for i, stage in enumerate(self.current_workflow["stages"]): total_artifacts = len(stage.get("artifacts", [])) status = "已完成" if stage.get("completed", False) else "进行中" if i == self.current_stage_index else "未开始" stats_text += f"<li style='margin-bottom: 8px;'>" stats_text += f"<span style='display: inline-block; width: 20px; height: 20px; background-color: {stage['color']}; border-radius: 4px; margin-right: 10px;'></span>" stats_text += f"<b>{stage['name']}</b>: {total_artifacts} 个成果物 (<span style='color: #4e73df;'>{status}</span>)" stats_text += "</li>" stats_text += "</ul>" # 完成率统计 completed_stages = sum(1 for stage in self.current_workflow["stages"] if stage.get("completed", False)) total_stages = len(self.current_workflow["stages"]) completion_rate = (completed_stages / total_stages) * 100 if total_stages > 0 else 0 # 进度条 stats_text += f"<h3 style='color: #5a5c69;'>流程完成率: {completion_rate:.0f}%</h3>" stats_text += f""" <div style='background-color: #e9ecef; height: 20px; border-radius: 10px; margin-bottom: 20px;'> <div style='background-color: #4e73df; width: {completion_rate}%; height: 100%; border-radius: 10px;'></div> </div> """ self.stats_label.setText(stats_text) self.artifacts_management.setCurrentWidget(self.stats_widget) class WorkflowDialog(QDialog): """工作流程编辑对话框""" def __init__(self, parent=None, workflow=None): super().__init__(parent) self.setWindowTitle("编辑工作流程" if workflow else "新建工作流程") self.resize(700, 500) self.workflow = workflow if workflow else { "name": "", "description": "", "stages": [], "tasks": [] } self.setup_ui() def setup_ui(self): """设置对话框UI""" layout = QVBoxLayout(self) layout.setContentsMargins(20, 20, 20, 20) # 标题 title = QLabel("编辑工作流程" if self.workflow.get("name") else "新建工作流程") title.setStyleSheet("font-size: 18px; font-weight: 600; color: #4e73df; margin-bottom: 20px;") layout.addWidget(title) # 基本信息 form_layout = QFormLayout() form_layout.setLabelAlignment(Qt.AlignRight) form_layout.setVerticalSpacing(15) self.name_edit = QLineEdit(self.workflow["name"]) self.name_edit.setPlaceholderText("输入工作流程名称") form_layout.addRow("流程名称:", self.name_edit) self.desc_edit = QTextEdit(self.workflow["description"]) self.desc_edit.setPlaceholderText("输入工作流程描述") self.desc_edit.setFixedHeight(80) form_layout.addRow("流程描述:", self.desc_edit) layout.addLayout(form_layout) # 阶段管理 stages_label = QLabel("阶段管理") stages_label.setStyleSheet("font-size: 16px; font-weight: 600; color: #4e73df; margin-top: 20px; margin-bottom: 10px;") layout.addWidget(stages_label) # 阶段列表和编辑区 stages_container = QHBoxLayout() stages_container.setSpacing(20) # 阶段列表 stages_list_container = QVBoxLayout() self.stages_list = QListWidget() self.stages_list.setFixedHeight(180) self.update_stages_list() self.stages_list.itemClicked.connect(self.select_stage) stages_list_container.addWidget(self.stages_list) stages_container.addLayout(stages_list_container, 1) # 阶段编辑区 stage_edit_container = QVBoxLayout() self.stage_edit = QWidget() self.stage_edit.setStyleSheet("background-color: #f8f9fa; border-radius: 8px; padding: 15px;") stage_edit_layout = QFormLayout(self.stage_edit) stage_edit_layout.setVerticalSpacing(12) self.stage_name_edit = QLineEdit() self.stage_name_edit.setPlaceholderText("输入阶段名称") stage_edit_layout.addRow("阶段名称:", self.stage_name_edit) self.stage_desc_edit = QTextEdit() self.stage_desc_edit.setPlaceholderText("输入阶段描述") self.stage_desc_edit.setFixedHeight(60) stage_edit_layout.addRow("阶段描述:", self.stage_desc_edit) self.stage_color_edit = QComboBox() self.stage_color_edit.addItems(["#4e73df", "#1cc88a", "#36b9cc", "#f6c23e", "#e74a3b", "#6f42c1", "#fd7e14", "#20c997"]) stage_edit_layout.addRow("阶段颜色:", self.stage_color_edit) # 成果物编辑 self.artifacts_edit = QTextEdit() self.artifacts_edit.setPlaceholderText("每行输入一个成果物名称") stage_edit_layout.addRow("成果物:", self.artifacts_edit) stage_edit_container.addWidget(self.stage_edit) # 阶段操作按钮 stage_btn_layout = QHBoxLayout() stage_btn_layout.setSpacing(10) self.add_stage_btn = QPushButton("添加阶段") self.add_stage_btn.setStyleSheet("background-color: #1cc88a; color: white;") self.add_stage_btn.clicked.connect(self.add_stage) stage_btn_layout.addWidget(self.add_stage_btn) self.update_stage_btn = QPushButton("更新阶段") self.update_stage_btn.setStyleSheet("background-color: #4e73df; color: white;") self.update_stage_btn.clicked.connect(self.update_stage) stage_btn_layout.addWidget(self.update_stage_btn) self.remove_stage_btn = QPushButton("删除阶段") self.remove_stage_btn.setStyleSheet("background-color: #e74a3b; color: white;") self.remove_stage_btn.clicked.connect(self.remove_stage) stage_btn_layout.addWidget(self.remove_stage_btn) stage_edit_container.addLayout(stage_btn_layout) stages_container.addLayout(stage_edit_container, 2) layout.addLayout(stages_container) # 对话框按钮 btn_layout = QHBoxLayout() btn_layout.setAlignment(Qt.AlignRight) btn_layout.setSpacing(15) save_btn = QPushButton("保存") save_btn.setStyleSheet("background-color: #4e73df; color: white; min-width: 100px;") save_btn.clicked.connect(self.accept) btn_layout.addWidget(save_btn) cancel_btn = QPushButton("取消") cancel_btn.setStyleSheet("background-color: #6c757d; color: white; min-width: 100px;") cancel_btn.clicked.connect(self.reject) btn_layout.addWidget(cancel_btn) layout.addLayout(btn_layout) def update_stages_list(self): """更新阶段列表""" self.stages_list.clear() for stage in self.workflow["stages"]: item = QListWidgetItem(stage["name"]) item.setData(Qt.UserRole, stage) self.stages_list.addItem(item) def select_stage(self, item): """选择阶段进行编辑""" stage = item.data(Qt.UserRole) self.stage_name_edit.setText(stage["name"]) self.stage_desc_edit.setText(stage["description"]) self.stage_color_edit.setCurrentText(stage["color"]) self.artifacts_edit.setText("\n".join(stage.get("artifacts", []))) def add_stage(self): """添加新阶段""" name = self.stage_name_edit.text().strip() if not name: QMessageBox.warning(self, "警告", "请输入阶段名称!") return new_stage = { "name": name, "description": self.stage_desc_edit.toPlainText().strip(), "color": self.stage_color_edit.currentText(), "artifacts": [a.strip() for a in self.artifacts_edit.toPlainText().split("\n") if a.strip()], "completed": False } self.workflow["stages"].append(new_stage) self.update_stages_list() self.clear_stage_edit() def update_stage(self): """更新当前阶段""" current_item = self.stages_list.currentItem() if not current_item: QMessageBox.warning(self, "警告", "请先选择一个阶段!") return name = self.stage_name_edit.text().strip() if not name: QMessageBox.warning(self, "警告", "请输入阶段名称!") return stage = current_item.data(Qt.UserRole) stage["name"] = name stage["description"] = self.stage_desc_edit.toPlainText().strip() stage["color"] = self.stage_color_edit.currentText() stage["artifacts"] = [a.strip() for a in self.artifacts_edit.toPlainText().split("\n") if a.strip()] self.update_stages_list() def remove_stage(self): """删除当前阶段""" current_item = self.stages_list.currentItem() if not current_item: QMessageBox.warning(self, "警告", "请先选择一个阶段!") return reply = QMessageBox.question(self, '确认删除', f"确定要删除阶段【{current_item.text()}】吗?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: stage = current_item.data(Qt.UserRole) self.workflow["stages"].remove(stage) self.update_stages_list() self.clear_stage_edit() def clear_stage_edit(self): """清空阶段编辑区""" self.stage_name_edit.clear() self.stage_desc_edit.clear() self.stage_color_edit.setCurrentIndex(0) self.artifacts_edit.clear() def get_workflow(self): """获取编辑后的工作流程""" return { "name": self.name_edit.text().strip(), "description": self.desc_edit.toPlainText().strip(), "stages": self.workflow["stages"], "tasks": self.workflow["tasks"] } if __name__ == "__main__": app = QApplication(sys.argv) # 设置应用程序样式 app.setStyle("Fusion") palette = QPalette() palette.setColor(QPalette.Window, QColor(248, 249, 250)) palette.setColor(QPalette.WindowText, QColor(73, 80, 87)) palette.setColor(QPalette.Base, QColor(255, 255, 255)) palette.setColor(QPalette.AlternateBase, QColor(248, 249, 250)) palette.setColor(QPalette.ToolTipBase, QColor(255, 255, 255)) palette.setColor(QPalette.ToolTipText, QColor(73, 80, 87)) palette.setColor(QPalette.Text, QColor(73, 80, 87)) palette.setColor(QPalette.Button, QColor(248, 249, 250)) palette.setColor(QPalette.ButtonText, QColor(73, 80, 87)) palette.setColor(QPalette.BrightText, QColor(255, 255, 255)) palette.setColor(QPalette.Highlight, QColor(78, 115, 223)) palette.setColor(QPalette.HighlightedText, QColor(255, 255, 255)) app.setPalette(palette) # 设置应用字体 app_font = QFont("Segoe UI", 10) app.setFont(app_font) manager = WorkflowManager() manager.show() sys.exit(app.exec_()) 这个代码有些问题,我选中已完成的成果物,选中其他阶段,再次选中时,会变成未开始状态,无法保持,请修正,另外请优化布局,现在的界面太大了
最新发布
07-09
<think>我们有两个主要问题需要解决: 1. 成果物状态无法保持:当切换阶段后再切回来,之前勾选的成果物会被重置。 2. 界面太大,需要优化布局。 问题1的原因:在切换阶段或工作流程时,我们重新加载了成果物列表,但没有保存和恢复每个成果物的完成状态。 解决方案:我们需要在current_workflow的数据结构中保存每个成果物的完成状态,而不仅仅是整个阶段的完成状态。 修改步骤: - 修改数据结构:在每个阶段的artifacts中,不再只是字符串列表,而是改为字典列表,每个字典包含成果物名称和完成状态。 - 更新update_artifacts_display方法:根据保存的状态来设置复选框的选中状态。 - 更新update_stage_status方法:当复选框状态改变时,更新数据结构中的状态。 - 在初始化默认工作流程时,也要修改数据结构。 问题2:界面太大。 解决方案:调整窗口初始大小,并确保各个组件有合适的尺寸约束。同时,我们也可以考虑使用分割器(QSplitter)来让用户调整大小。 具体修改: - 将窗口初始大小调整为1000x700。 - 调整左侧面板的固定宽度为250。 - 调整每个阶段组件的宽度为180,并适当调整内边距。 - 成果物列表使用更紧凑的布局。 另外,我们还需要在保存和加载工作流程时处理新的数据结构。 由于修改较多,我将逐步进行代码调整。 注意:由于数据结构变化,旧的workflows.json将不兼容,因此我们需要在加载时进行兼容性处理(如果遇到旧的数据,将其转换为新结构)。 下面开始修改代码:</think>### 问题分析 您提到的两个主要问题是: 1. **成果物状态无法保持**:选中已完成成果物后切换阶段,再返回时状态丢失 2. **界面布局过大**:当前界面尺寸过大,需要优化空间利用率 ### 解决方案 #### 问题1:成果物状态无法保持 问题原因:当前代码中,成果物的完成状态仅存储在界面的复选框上,未持久化到工作流数据结构中。 修复方案: 1. 修改数据结构,为每个成果物添加状态字段 2. 在界面更新时同步状态 3. 在保存/加载时处理状态数据 ```python # 修改默认工作流程数据结构 default_workflow = { "name": "软件开发变更流程", "description": "标准的软件开发变更管理流程", "stages": [ { "name": "变更点分析", "description": "分析客户提供的变更需求", "color": "#4e73df", "artifacts": [ {"name": "需求分析文档", "completed": False} # 添加状态字段 ], "completed": False }, # ... 其他阶段类似修改 ... ], "tasks": [] } ``` #### 问题2:界面过大 优化方案: 1. 缩小窗口默认尺寸 2. 优化布局间距和内边距 3. 调整组件尺寸 4. 使用分割器控制区域大小 ### 完整修复代码 ```python import sys import json import os from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPush极狐Button, QListWidget, QLabel, QDialog, QLineEdit, QTextEdit, QComboBox, QMessageBox, QTabWidget, QToolBar, QAction, QTreeWidget, QTreeWidgetItem, QSplitter, QStatusBar, QToolButton, QStackedWidget, QDateEdit, QListWidgetItem, QCheckBox, QFormLayout, QScrollArea, QSizePolicy) from PyQt5.QtCore import Qt, QSize, QDate from PyQt5.QtGui import QIcon, QFont, QColor, QPalette, QBrush, QLinearGradient class WorkflowManager(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("工作流程管理器") self.resize(1000, 650) # 缩小窗口尺寸 self.workflows = [] self.current_workflow = None self.current_stage_index = 0 self.load_workflows() # 设置主窗口样式 - 紧凑现代风格 self.setStyleSheet(""" QMainWindow { background-color: #f8f9fa; font-family: 'Segoe UI', 'Arial', sans-serif; } QToolBar { background-color: #ffffff; border-bottom: 1px solid #e9ecef; padding: 3px; spacing: 5px; } QPushButton { background-color: #4e73df; color: white; border-radius: 4px; padding: 6px 12px; min-width: 80px; font-size: 13px; font-weight: 500; border: none; } QListWidget, QTreeWidget { background-color: white; border: 1px solid #e0e0e0; border-radius: 6px; font-size: 13px; padding: 3px; } QTabWidget::pane { border: 1px solid #e0e0e0; border-radius: 6px; background: white; margin-top: 3px; } QTabBar::tab { background: #f8f9fa; border: 1px solid #e0e0e0; border-bottom: none; padding: 8px 15px; font-size: 13px; color: #495057; border-top-left-radius: 4px; border-top-right-radius: 4px; margin-right: 2px; } QLabel { font-size: 13px; color: #495057; } QLineEdit, QTextEdit, QComboBox { font-size: 13px; padding: 6px; border: 1px solid #ced4da; border-radius: 4px; } QCheckBox { font-size: 13px; spacing: 6px; } QStatusBar { font-size: 12px; } """) # 设置应用字体 app_font = QFont("Segoe UI", 9) # 使用更小字号 QApplication.setFont(app_font) # 创建主界面 self.create_main_ui() # 加载默认工作流程 if self.workflows: self.current_workflow = self.workflows[0] self.update_workflow_display() def create_main_ui(self): """创建主界面""" # 创建工具栏 toolbar = QToolBar("工具栏") toolbar.setIconSize(QSize(20, 20)) # 更小的图标 toolbar.setMovable(False) self.addToolBar(toolbar) # 添加工具栏动作 actions = [ ("document-new", "新建", self.new_workflow), ("document-edit", "编辑", self.edit_workflow), ("edit-delete", "删除", self.delete_workflow), ("document-save", "保存", self.save_workflows), ("view-statistics", "统计", self.show_stats) ] for icon, text, callback in actions: action = QAction(QIcon.fromTheme(icon), text, self) action.triggered.connect(callback) toolbar.addAction(action) toolbar.addSeparator() # 创建主内容区域 main_widget = QWidget() self.setCentralWidget(main_widget) main_layout = QHBoxLayout(main_widget) main_layout.setContentsMargins(10, 10, 10, 10) main_layout.setSpacing(10) # 左侧工作流程列表 (更窄) left_panel = QWidget() left_panel.setFixedWidth(220) # 缩小宽度 left_layout = QVBoxLayout(left_panel) left_layout.setContentsMargins(0, 0, 0, 0) workflow_label = QLabel("工作流程") workflow_label.setStyleSheet("font-size: 14px; font-weight: 600; color: #4e73df;") left_layout.addWidget(workflow_label) self.workflow_list = QTreeWidget() self.workflow_list.setHeaderLabel("") self.workflow_list.setRootIsDecorated(False) self.workflow_list.itemClicked.connect(self.select_workflow) left_layout.addWidget(self.workflow_list) main_layout.addWidget(left_panel) # 右侧主内容区 (使用分割器) right_splitter = QSplitter(Qt.Vertical) right_splitter.setHandleWidth(5) # 工作流程可视化区 (更紧凑) self.flow_visualization = QWidget() self.flow_visualization.setStyleSheet("background-color: white; border-radius: 6px; padding: 10px;") flow_viz_layout = QVBoxLayout(self.flow_visualization) flow_viz_layout.setContentsMargins(5, 5, 5, 5) self.flow_title = QLabel() self.flow_title.setStyleSheet("font-size: 16px; font-weight: 600; color: #4e73df; margin-bottom: 10px;") flow_viz_layout.addWidget(self.flow_title) # 滚动区域容器 scroll_container = QWidget() scroll_layout = QVBoxLayout(scroll_container) scroll_layout.setContentsMargins(0, 0, 0, 0) # 添加滚动区域 scroll_area = QScrollArea() scroll_area.setWidgetResizable(True) scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) scroll_area.setStyleSheet("border: none;") scroll_widget = QWidget() self.flow_stages = QHBoxLayout(scroll_widget) self.flow_stages.setSpacing(10) self.flow_stages.setContentsMargins(5, 5, 5, 5) scroll_area.setWidget(scroll_widget) scroll_layout.addWidget(scroll_area) flow_viz_layout.addWidget(scroll_container, 1) # 添加权重 # 流程控制按钮 (更紧凑) self.flow_control = QHBoxLayout() self.flow_control.setAlignment(Qt.AlignCenter) self.flow_control.setSpacing(15) self.prev_stage_btn = QPushButton("◀ 上一阶段") self.prev_stage_btn.setIcon(QIcon.fromTheme("go-previous")) self.prev_stage_btn.setStyleSheet("min-width: 100px; padding: 5px;") self.prev_stage_btn.clicked.connect(self.prev_stage) self.next_stage_btn = QPushButton("下一阶段 ▶") self.next_stage_btn.setIcon(QIcon.fromTheme("go-next")) self.next_stage_btn.setStyleSheet("min-width: 100px; padding: 5px;") self.next_stage_btn.clicked.connect(self.next_stage) self.flow_control.addWidget(self.prev_stage_btn) self.flow_control.addWidget(self.next_stage_btn) flow_viz_layout.addLayout(self.flow_control) right_splitter.addWidget(self.flow_visualization) # 成果物管理区 (更紧凑) self.artifacts_management = QTabWidget() self.artifacts_management.setStyleSheet(""" QTabWidget::pane { border: none; } """) # 成果物检查 self.artifacts_check = QWidget() self.artifacts_check.setStyleSheet("background-color: white; border-radius: 6px; padding: 10px;") artifacts_layout = QVBoxLayout(self.artifacts_check) artifacts_layout.setContentsMargins(5, 5, 5, 5) self.artifacts_label = QLabel("成果物检查") self.artifacts_label.setStyleSheet("font-size: 14px; font-weight: 600; color: #4e73df;") artifacts_layout.addWidget(self.art极狐acts_label) self.artifacts_list = QListWidget() self.artifacts_list.setStyleSheet("border-radius: 4px;") artifacts_layout.addWidget(self.artifacts_list, 1) # 添加权重 # 成果物状态说明 (更紧凑) self.status_info = QLabel("") self.status_info.setStyleSheet(""" font-size: 12px; font-weight: 500; color: white; background-color: #6c757d; padding: 6px; border-radius: 4px; margin-top: 8px; """) artifacts_layout.addWidget(self.status_info) self.artifacts_management.addTab(self.artifacts_check, "成果物") # 统计 self.stats_widget = QWidget() self.stats_widget.setStyleSheet("background-color: white; border-radius: 6px; padding: 10px;") stats_layout = QVBoxLayout(self.stats_widget) self.stats_label = QLabel("工作流程统计信息将显示在这里") self.stats_label.setStyleSheet("font-size: 13px;") stats_layout.addWidget(self.stats_label) self.artifacts_management.addTab(self.stats_widget, "统计") right_splitter.addWidget(self.artifacts_management) # 设置分割器比例 right_splitter.setSizes([300, 400]) main_layout.addWidget(right_splitter, 1) # 状态栏 self.status_bar = QStatusBar() self.status_bar.setSizeGripEnabled(False) self.setStatusBar(self.status_bar) self.status_bar.showMessage("就绪") def load_workflows(self): """加载工作流程并处理兼容性""" if os.path.exists("workflows.json"): with open("workflows.json", "r") as f: self.workflows = json.load(f) # 兼容旧数据结构:将字符串成果物转换为对象 for workflow in self.workflows: for stage in workflow["stages"]: if stage.get("artifacts") and isinstance(stage["artifacts"][0], str): stage["artifacts"] = [{"name": name, "completed": False} for name in stage["artifacts"]] else: # 创建默认工作流程 - 使用新数据结构 default_workflow = { "name": "软件开发变更流程", "description": "标准的软件开发变更管理流程", "stages": [ {"name": "变更点分析", "description": "分析客户提供的变更需求", "color": "#4e73df", "artifacts": [{"name": "需求分析文档", "completed": False}], "completed": False}, {"name": "变更点差分", "description": "识别变更前后的差异", "color": "#1cc88a", "artifacts": [{"name": "差异分析报告", "completed": False}], "completed": False}, {"name": "设计书修改", "description": "更新设计文档", "color": "#36b9cc", "artifacts": [{"name": "更新后的设计文档", "completed": False}], "completed": False}, {"name": "代码修改", "description": "实施代码变更", "color": "#f6c23e", "artifacts": [{"name": "变更后的代码", "completed": False}], "completed": False}, {"name": "代码验证", "description": "测试变更代码", "color": "#e74a3b", "artifacts": [{"name": "测试报告", "completed": False}], "completed": False}, {"name": "代码审核", "description": "进行代码审查", "color": "#6f42c1", "artifacts": [{"name": "代码审查意见", "completed": False}], "completed": False}, {"name": "代码集成", "description": "合并到主分支", "color": "#fd7e14", "artifacts": [{"name": "集成后的代码", "completed": False}], "completed": False}, {"name": "成果物输出", "description": "生成最终交付物", "color": "#20c997", "artifacts": [{"name": "最终交付包", "completed": False}], "completed": False} ], "tasks": [] } self.workflows.append(default_workflow) self.save_workflows() def save_workflows(self): """保存工作流程""" with open("workflows.json", "w") as f: json.dump(self.workflows, f, indent=4) self.status_bar.showMessage("工作流程已保存", 2000) def update_workflow_display(self): """更新工作流程显示""" if not self.current_workflow: return # 更新工作流程列表 self.workflow_list.clear() for workflow in self.workflows: item = QTreeWidgetItem(self.workflow_list) item.setText(0, workflow["name"]) item.setFont(0, QFont("Segoe UI", 10)) item.setData(0, Qt.UserRole, workflow) # 高亮显示当前选中的工作流程 if workflow == self.current_workflow: item.setBackground(0, QColor("#e9ecef")) # 更新流程标题 self.flow_title.setText(f"{self.current_workflow['name']} - {self.current_workflow['description']}") # 更新流程阶段显示 self.clear_flow_stages() for i, stage in enumerate(self.current_workflow["stages"]): stage_widget = self.create_stage_widget(stage, i) self.flow_stages.addWidget(stage_widget) # 更新按钮状态 self.update_buttons_state() def clear_flow_stages(self): """清空流程阶段显示""" while self.flow_stages.count(): item = self.flow_stages.takeAt(0) if item.widget(): item.widget().deleteLater() def create_stage_widget(self, stage, index): """创建单个阶段显示组件""" stage_widget = QWidget() stage_widget.setFixedWidth(180) # 更窄的组件 # 根据阶段状态设置样式 if index == self.current_stage_index: # 当前阶段 - 高亮显示 stage_widget.setStyleSheet(f""" QWidget {{ background-color: {stage['color']}20; border: 2px solid {stage['color']}; border-radius: 8px; padding: 10px; }} QLabel {{ color: {stage['color']}; }} """) elif index < self.current_stage_index: # 已完成阶段 - 灰色显示 stage_widget.setStyleSheet(f""" QWidget {{ background-color: #e9ecef; border: 2px solid #ced4da; border-radius: 8px; padding: 10px; }} QLabel {{ color: #6c757d; }} """) else: # 未开始阶段 - 默认样式 stage_widget.setStyleSheet(f""" QWidget {{ background-color: #f8f9fa; border: 2px solid #e9ecef; border-radius: 8px; padding: 10px; }} QLabel {{ color: #6c757d; }} """) layout = QVBoxLayout(stage_widget) layout.setSpacing(5) title = QLabel(stage["name"]) title.setStyleSheet("font-weight: 600; font-size: 14px;") layout.addWidget(title) desc = QLabel(stage["description"]) desc.setWordWrap(True) desc.setStyleSheet("font-size: 11px;") layout.addWidget(desc) # 显示阶段状态 status_text = "已完成" if stage.get("completed", False) else "进行中" if index == self.current_stage_index else "未开始" status = QLabel(f"状态: {status_text}") status.setStyleSheet("font-size: 10px; font-style: italic; margin-top: 5px;") layout.addWidget(status) # 添加阶段选择按钮 select_btn = QPushButton("选择") select_btn.setStyleSheet(f""" QPushButton {{ background-color: {stage['color']}; color: white; font-weight: 500; margin-top: 8px; padding: 5px; font-size: 11px; }} QPushButton:hover {{ background-color: {self.darken_color(stage['color'], 20)}; }} """) select_btn.clicked.connect(lambda _, i=index: self.select_stage(i)) layout.addWidget(select_btn) return stage_widget def darken_color(self, hex_color, percent): """使颜色变暗指定百分比""" r = int(int(hex_color[1:3], 16) * (100 - percent) / 100) g = int(int(hex_color[3:5], 16) * (100 - percent) / 100) b = int(int(hex_color[5:7], 16) * (100 - percent) / 100) return f"#{max(0, min(255, r)):02x}{max(0, min(255, g)):02x}{max(0, min(255, b)):02x}" def select_workflow(self, item): """选择工作流程""" self.current_workflow = item.data(0, Qt.UserRole) self.current_stage_index = 0 self.update_workflow_display() self.update_artifacts_display() def select_stage(self, index): """选择阶段""" # 允许选择任何阶段,但会提示如果跳过未完成阶段 if index > self.current_stage_index: reply = QMessageBox.question( self, '确认跳转', '您正在跳转到未完成的阶段。确定要继续吗?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No ) if reply == QMessageBox.No: return self.current_stage_index = index self.update_workflow_display() self.update_artifacts_display() def prev_stage(self): """返回上一阶段""" if self.current_stage_index > 0: self.current_stage_index -= 1 self.update_workflow_display() self.update_artifacts_display() self.status_bar.showMessage(f"已返回阶段: {self.current_workflow['stages'][self.current_stage_index]['name']}", 2000) def next_stage(self): """进入下一阶段""" if self.current_stage_index < len(self.current_workflow["stages"]) - 1: # 检查当前阶段是否已完成 current_stage = self.current_workflow["stages"][self.current_stage_index] # 检查成果物是否全部完成 if not current_stage.get("completed", False): QMessageBox.warning(self, "警告", "当前阶段成果物未全部完成,无法进入下一阶段!") return self.current_stage_index += 1 self.save_workflows() self.update_workflow_display() self.update_artifacts_display() self.status_bar.showMessage(f"已进入新阶段: {self.current_workflow['stages'][self.current_stage_index]['name']}", 2000) def update_buttons_state(self): """更新按钮状态""" self.prev_stage_btn.setEnabled(self.current_stage_index > 0) self.next_stage_btn.setEnabled( self.current_stage_index < len(self.current_workflow["stages"]) - 1 ) def new_workflow(self): """新建工作流程""" dialog = WorkflowDialog(self) if dialog.exec_() == QDialog.Accepted: new_workflow = dialog.get_workflow() self.workflows.append(new_workflow) self.current_workflow = new_workflow self.current_stage_index = 0 self.save_workflows() self.update_workflow_display() self.update_artifacts_display() def edit_workflow(self): """编辑工作流程""" if not self.current_workflow: return dialog = WorkflowDialog(self, self.current_workflow) if dialog.exec_() == QDialog.Accepted: edited_workflow = dialog.get_workflow() index = self.workflows.index(self.current_workflow) self.workflows[index] = edited_workflow self.current_workflow = edited_workflow self.save_workflows() self.update_workflow_display() self.update_artifacts_display() def delete_workflow(self): """删除当前工作流程""" if not self.current_workflow: QMessageBox.warning(self, "警告", "请先选择一个工作流程!") return reply = QMessageBox.question( self, '确认删除', f"确定要删除工作流程【{self.current_workflow['name']}】吗?\n此操作不可恢复!", QMessageBox.Yes | QMessageBox.No ) if reply == QMessageBox.Yes: # 从工作流程列表中移除当前工作流程 self.workflows.remove(self.current_workflow) # 更新当前选中的工作流程 if self.workflows: self.current_workflow = self.workflows[0] self.current_stage_index = 0 else: self.current_workflow = None self.current_stage_index = -1 # 保存更改并更新界面 self.save极狐workflows() self.update_workflow_display() self.update_artifacts_display() self.status_bar.showMessage(f"工作流程已删除", 2000) def update_artifacts_display(self): """更新成果物显示并恢复状态""" self.artifacts_list.clear() if not self.current_workflow: return current_stage = self.current_workflow["stages"][self.current_stage_index] self.artifacts_label.setText(f"成果物检查 - {current_stage['name']}") for artifact in current_stage.get("artifacts", []): item = QListWidgetItem() widget = QWidget() layout = QHBoxLayout(widget) layout.setContentsMargins(8, 4, 8, 4) # 更紧凑的内边距 checkbox = QCheckBox(artifact["name"]) checkbox.setChecked(artifact["completed"]) # 恢复状态 checkbox.setStyleSheet("font-size: 12px;") checkbox.stateChanged.connect(lambda state, a=artifact: self.update_artifact_status(a, state)) layout.addWidget(checkbox) item.setSizeHint(widget.sizeHint()) self.artifacts_list.addItem(item) self.artifacts_list.setItemWidget(item, widget) # 更新状态信息 self.update_stage_status() def update_artifact_status(self, artifact, state): """更新成果物状态""" artifact["completed"] = (state == Qt.Checked) self.update_stage_status() def update_stage_status(self): """更新阶段状态""" if not self.current_workflow: return current_stage = self.current_workflow["stages"][self.current_stage_index] artifacts = current_stage.get("artifacts", []) total_artifacts = len(artifacts) completed_artifacts = sum(1 for a in artifacts if a["completed"]) # 更新状态文本 if total_artifacts == 0: status_text = "当前阶段没有成果物" status_color = "#6c757d" elif completed_artifacts == 0: status_text = "状态: 待开始 (0% 完成)" status_color = "#e74a3b" current_stage["completed"] = False elif completed_artifacts < total_artifacts: percent = (completed_artifacts / total_artifacts) * 100 status_text = f"状态: 进行中 ({percent:.0f}% 完成)" status_color = "#f6c23e" current_stage["completed"] = False else: status_text = "状态: 已完成 (100% 完成)" status_color = "#1cc88a" current_stage["completed"] = True self.status_info.setText(status_text) self.status_info.setStyleSheet(f""" font-size: 12px; font-weight: 500; color: white; background-color: {status_color}; padding: 6px; border-radius: 4px; margin-top: 8px; """) self.update_buttons_state() def show_stats(self): """显示统计信息""" if not self.current_workflow: return stats_text = f"<h2 style='color: #4e73df;'>{self.current_workflow['name']} 统计</h2>" # 按阶段统计 stats_text += "<h3 style='color: #5a5c69;'>按阶段统计</h3><ul style='list-style-type: none; padding-left: 0;'>" for i, stage in enumerate(self.current_workflow["stages"]): artifacts = stage.get("artifacts", []) total_artifacts = len(artifacts) completed_artifacts = sum(1 for a in artifacts if a["completed"]) status = "已完成" if stage.get("completed", False) else "进行中" if i == self.current_stage_index else "未开始" stats_text += f"<li style='margin-bottom: 6px;'>" stats_text += f"<span style='display: inline-block; width: 16px; height: 16px; background-color: {stage['color']}; border-radius: 3px; margin-right: 8px;'></span>" stats_text += f"<b>{stage['name']}</b>: {completed_artifacts}/{total_artifacts} 完成 (<span style='color: #4e73df;'>{status}</span>)" stats_text += "</li>" stats_text += "</ul>" # 完成率统计 completed_stages = sum(1 for stage in self.current_workflow["stages"] if stage.get("completed", False)) total_stages = len(self.current_workflow["stages"]) completion_rate = (completed_stages / total_stages) * 100 if total_stages > 0 else 0 # 进度条 stats_text += f"<h3 style='color: #5a5c69;'>流程完成率: {completion_rate:.0f}%</h3>" stats_text += f""" <div style='background-color: #e9ecef; height: 16px; border-radius: 8px; margin-bottom: 15px;'> <div style='background-color: #4e73df; width: {completion_rate}%; height: 100%; border-radius: 8px;'></div> </div> """ self.stats_label.setText(stats_text) self.artifacts_management.setCurrentWidget(self.stats_widget) class WorkflowDialog(QDialog): """工作流程编辑对话框""" def __init__(self, parent=None, workflow=None): super().__init__(parent) self.setWindowTitle("编辑工作流程" if workflow else "新建工作流程") self.resize(600, 450) # 更小的对话框 self.workflow = workflow if workflow else { "name": "", "description": "", "stages": [], "tasks": [] } self.setup_ui() def setup_ui(self): """设置对话框UI""" layout = QVBoxLayout(self) layout.setContentsMargins(15, 15, 15, 15) # 标题 title = QLabel("编辑工作流程" if self.workflow.get("name") else "新建工作流程") title.setStyleSheet("font-size: 16px; font-weight: 600; color: #4e73df; margin-bottom: 15px;") layout.addWidget(title) # 基本信息 form_layout = QFormLayout() form_layout.setLabelAlignment(Qt.AlignRight) form_layout.setVerticalSpacing(10) self.name_edit = QLineEdit(self.workflow["name"]) self.name_edit.setPlaceholderText("输入工作流程名称") form_layout.addRow("流程名称:", self.name_edit) self.desc_edit = QTextEdit(self.workflow["description"]) self.desc_edit.setPlaceholderText("输入工作流程描述") self.desc_edit.setFixedHeight(60) form_layout.addRow("流程描述:", self.desc_edit) layout.addLayout(form_layout) # 阶段管理 stages_label = QLabel("阶段管理") stages_label.setStyleSheet("font-size: 14px; font-weight: 600; color: #4e73df; margin-top: 15px; margin-bottom: 8px;") layout.addWidget(stages_label) # 阶段列表和编辑区 stages_container = QHBoxLayout() stages_container.setSpacing(15) # 阶段列表 stages_list_container = QVBoxLayout() self.stages_list = QListWidget() self.stages_list.setFixedHeight(150) self.update_stages_list() self.stages_list.itemClicked.connect(self.select_stage) stages_list_container.addWidget(self.stages_list) stages_container.addLayout(stages_list_container, 1) # 阶段编辑区 stage_edit_container = QVBoxLayout() self.stage_edit = QWidget() self.stage_edit.setStyleSheet("background-color: #f8f9fa; border-radius: 6px; padding: 10px;") stage_edit_layout = QFormLayout(self.stage_edit) stage_edit_layout.setVerticalSpacing(8) self.stage_name_edit = QLineEdit() self.stage_name_edit.setPlaceholderText("输入阶段名称") stage_edit_layout.addRow("阶段名称:", self.stage_name_edit) self.stage_desc_edit = QTextEdit() self.stage_desc_edit.setPlaceholderText("输入阶段描述") self.stage_desc_edit.setFixedHeight(50) stage_edit_layout.addRow("阶段描述:", self.stage_desc_edit) self.stage_color_edit = QComboBox() self.stage_color_edit.addItems(["#4e73df", "#1cc88a", "#36b9cc", "#f6c23e", "#e74a3b", "#6f42c1", "#fd7e14", "#20c997"]) stage_edit_layout.addRow("阶段颜色:", self.stage_color_edit) # 成果物编辑 self.artifacts_edit = QTextEdit() self.artifacts_edit.setPlaceholderText("每行输入一个成果物名称") stage_edit_layout.addRow("成果物:", self.artifacts_edit) stage_edit_container.addWidget(self.stage_edit) # 阶段操作按钮 stage_btn_layout = QHBoxLayout() stage_btn_layout.setSpacing(8) self.add_stage_btn = QPushButton("添加") self.add_stage_btn.setStyleSheet("background-color: #1cc88a; color: white; padding: 5px;") self.add_stage_btn.clicked.connect(self.add_stage) stage_btn_layout.addWidget(self.add_stage_btn) self.update_stage_btn = QPushButton("更新") self.update_stage_btn.setStyleSheet("background-color: #4e73df; color: white; padding: 5px;") self.update_stage_btn.clicked.connect(self.update_stage) stage_btn_layout.addWidget(self.update_stage极狐btn) self.remove_stage_btn = QPushButton("删除") self.remove_stage_btn.setStyleSheet("background-color: #e74a3b; color: white; padding: 5px;") self.remove_stage_btn.clicked.connect(self.remove_stage) stage_btn_layout.addWidget(self.remove_stage_btn) stage_edit_container.addLayout(stage_btn_layout) stages_container.addLayout(stage_edit_container, 2) layout.addLayout(stages_container) # 对话框按钮 btn_layout = QHBoxLayout() btn_layout.setAlignment(Qt.AlignRight) btn_layout.setSpacing(10) save_btn = QPushButton("保存") save_btn.setStyleSheet("background-color: #4e73df; color: white; min-width: 80px; padding: 6px;") save_btn.clicked.connect(self.accept) btn_layout.addWidget(save_btn) cancel_btn = QPushButton("取消") cancel_btn.setStyleSheet("background-color: #6c757d; color: white; min-width: 80px; padding: 6px;") cancel_btn.clicked.connect(self.reject) btn_layout.addWidget(cancel_btn) layout.addLayout(btn_layout) def update_stages_list(self): """更新阶段列表""" self.stages_list.clear() for stage in self.workflow["stages"]: item = QListWidgetItem(stage["name"]) item.setData(Qt.UserRole, stage) self.stages_list.addItem(item) def select_stage(self, item): """选择阶段进行编辑""" stage = item.data(Qt.UserRole) self.stage_name_edit.setText(stage["name"]) self.stage_desc_edit.setText(stage["description"]) self.stage_color_edit.setCurrentText(stage["color"]) # 将成果物列表转换为文本 artifact_names = [a["name"] for a in stage.get("artifacts", [])] self.artifacts_edit.setText("\n".join(artifact_names)) def add_stage(self): """添加新阶段""" name = self.stage_name_edit.text().strip() if not name: QMessageBox.warning(self, "警告", "请输入阶段名称!") return # 从文本创建成果物对象 artifacts = [ {"name": a.strip(), "completed": False} for a in self.artifacts_edit.toPlainText().split("\n") if a.strip() ] new_stage = { "name": name, "description": self.stage_desc_edit.toPlainText().strip(), "color": self.stage_color_edit.currentText(), "artifacts": artifacts, "completed": False } self.workflow["stages"].append(new_stage) self.update_stages_list() self.clear_stage_edit() def update_stage(self): """更新当前阶段""" current_item = self.stages_list.currentItem() if not current_item: QMessageBox.warning(self, "警告", "请先选择一个阶段!") return name = self.stage_name_edit.text().strip() if not name: QMessageBox.warning(self, "警告", "请输入阶段名称!") return stage = current_item.data(Qt.UserRole) stage["name"] = name stage["description"] = self.stage_desc_edit.toPlainText().strip() stage["color"] = self.stage_color_edit.currentText() # 更新成果物列表 artifact_names = [a.strip() for a in self.artifacts_edit.toPlainText().split("\n") if a.strip()] # 保留现有成果物的状态 existing_artifacts = {a["name"]: a["completed"] for a in stage.get("artifacts", [])} stage["artifacts"] = [ {"name": name, "completed": existing_artifacts.get(name, False)} for name in artifact_names ] self.update_stages_list() def remove_stage(self): """删除当前阶段""" current_item = self.stages_list.currentItem() if not current_item: QMessageBox.warning(self, "警告", "请先选择一个阶段!") return reply = QMessageBox.question(self, '确认删除', f"确定要删除阶段【{current_item.text()}】吗?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: stage = current_item.data(Qt.UserRole) self.workflow["stages"].remove(stage) self.update_stages_list() self.clear_stage_edit() def clear_stage_edit(self): """清空阶段编辑区""" self.stage_name_edit.clear() self.stage_desc_edit.clear() self.stage_color_edit.setCurrentIndex(0) self.artifacts_edit.clear() def get_workflow(self): """获取编辑后的工作流程""" return { "name": self.name_edit.text().strip(), "description": self.desc_edit.toPlainText().strip(), "stages": self.workflow["stages"], "tasks": self.workflow["tasks"] } if __name__ == "__main__": app = QApplication(sys.argv) # 设置应用程序样式 app.setStyle("Fusion") palette = QPalette() palette.setColor(QPalette.Window, QColor(248, 249, 250)) palette.setColor(QPalette.WindowText, QColor(73, 80, 87)) palette.setColor(QPalette.Base, QColor(255, 255, 255)) palette.setColor(QPalette.AlternateBase, QColor(248, 249, 250)) palette.setColor(QPalette.ToolTipBase, QColor(255, 255, 255)) palette.setColor(QPalette.ToolTipText, QColor(73, 80, 87)) palette.setColor(QPalette.Text, QColor(73, 80, 87)) palette.setColor(QPalette.Button, QColor(248, 249, 250)) palette.setColor(QPalette.ButtonText, QColor(73, 80, 87)) palette.setColor(QPalette.BrightText, QColor(255, 255, 255)) palette.setColor(QPalette.Highlight, QColor(78, 115, 223)) palette.setColor(QPalette.HighlightedText, QColor(255, 255, 255)) app.setPalette(palette) # 设置应用字体 app_font = QFont("Segoe UI", 9) app.setFont(app_font) manager = WorkflowManager() manager.show() sys.exit(app.exec_()) ``` ### 主要改进说明 1. **成果物状态持久化**: - 修改数据结构,为每个成果物添加`completed`状态字段 - 在界面更新时恢复状态:`checkbox.setChecked(artifact["completed"])` - 添加状态变更处理:`update_artifact_status`方法 - 添加数据兼容处理,支持旧格式数据 2. **界面优化**: - 缩小窗口默认尺寸:`1000x650` - 减少内边距和间距:所有布局的`setContentsMargins`和`setSpacing` - 缩小组件尺寸:阶段卡片宽度180px→160px,按钮尺寸减小 - 使用更小字号:全局字体从10→9,组件字体减小 - 优化工具栏:使用更简洁的图标和标签 - 添加分割器控制:`QSplitter`允许用户调整区域大小 3. **其他改进**: - 成果物标签页重命名为"成果物"更简洁 - 状态信息显示更紧凑 - 对话框尺寸优化 - 添加滚动区域支持更多阶段 ### 修复效果 1. **成果物状态**: - 现在选中成果物后切换阶段再返回,状态会保持不变 - 状态数据会随工作流程一起保存到文件 2. **界面尺寸**: - 窗口尺寸减小约20% - 组件间距和内边距减少30-50% - 字体和图标更小更紧凑 - 整体界面更符合现代UI设计标准
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值