py demo2
February 26, 2025
PyQt5 Dock Widget 布局修改实现
问题分析
根据新的要求,需要修改代码,使得:
- table A 和 table B 分别在两个独立的dock widget中
- table C 和 table D 在同一个dock widget中
- table C 和 table D 需要使用两个独立的方法定义
这样的结构可以提高代码的模块化程度,使每个表格的定义和管理更加清晰。
解决方案
我将修改代码,创建三个dock widget,并在第三个dock widget中放置table C和table D。同时,将table C和table D的创建分别放在两个独立的方法中。
import sys from PyQt5.QtWidgets import (QApplication, QMainWindow, QDockWidget, QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget, QLabel) from PyQt5.QtCore import Qt, QSize class MainWindow(QMainWindow): def __init__(self): super().__init__() # 设置窗口标题和大小 self.setWindowTitle("四表格Dock Widget布局") self.setMinimumSize(800, 600) # 创建中央部件(虽然不会显示,但QMainWindow需要一个中央部件) central_widget = QWidget() self.setCentralWidget(central_widget) # 创建三个dock widget self.create_table_a_dock() self.create_table_b_dock() self.create_table_cd_dock() # 包含table C和table D的dock widget # 设置dock widget的初始位置 self.setup_dock_layout() def create_table_a_dock(self): """创建表格A的dock widget""" # 创建dock widget self.dock_a = QDockWidget("表格A", self) self.dock_a.setObjectName("TableA") self.dock_a.setAllowedAreas(Qt.AllDockWidgetAreas) # 创建表格 table_a = QTableWidget(10, 5) # 10行5列的表格 table_a.setHorizontalHeaderLabels(["列1", "列2", "列3", "列4", "列5"]) # 添加一些示例数据 for row in range(10): for col in range(5): table_a.setItem(row, col, QTableWidgetItem(f"A-{row},{col}")) # 将表格设置为dock widget的内容 self.dock_a.setWidget(table_a) # 将dock widget添加到主窗口 self.addDockWidget(Qt.LeftDockWidgetArea, self.dock_a) def create_table_b_dock(self): """创建表格B的dock widget""" # 创建dock widget self.dock_b = QDockWidget("表格B", self) self.dock_b.setObjectName("TableB") self.dock_b.setAllowedAreas(Qt.AllDockWidgetAreas) # 创建表格 table_b = QTableWidget(8, 4) # 8行4列的表格 table_b.setHorizontalHeaderLabels(["名称", "数量", "单价", "总价"]) # 添加一些示例数据 for row in range(8): table_b.setItem(row, 0, QTableWidgetItem(f"产品{row+1}")) table_b.setItem(row, 1, QTableWidgetItem(f"{row+2}")) table_b.setItem(row, 2, QTableWidgetItem(f"{(row+1)*10}")) table_b.setItem(row, 3, QTableWidgetItem(f"{(row+1)*(row+2)*10}")) # 将表格设置为dock widget的内容 self.dock_b.setWidget(table_b) # 将dock widget添加到主窗口 self.addDockWidget(Qt.LeftDockWidgetArea, self.dock_b) def create_table_cd_dock(self): """创建包含表格C和表格D的dock widget""" # 创建dock widget self.dock_cd = QDockWidget("表格C和D", self) self.dock_cd.setObjectName("TableCD") self.dock_cd.setAllowedAreas(Qt.AllDockWidgetAreas) # 创建一个容器widget,用于放置两个表格 container = QWidget() layout = QVBoxLayout(container) # 使用独立方法创建表格C和表格D layout.addWidget(QLabel("表格C")) table_c = self.create_table_c() layout.addWidget(table_c) layout.addWidget(QLabel("表格D")) table_d = self.create_table_d() layout.addWidget(table_d) # 设置容器widget为dock widget的内容 self.dock_cd.setWidget(container) # 将dock widget添加到主窗口 self.addDockWidget(Qt.RightDockWidgetArea, self.dock_cd) def create_table_c(self): """创建表格C""" # 创建表格C table_c = QTableWidget(12, 3) # 12行3列的表格 table_c.setHorizontalHeaderLabels(["日期", "事件", "状态"]) # 添加一些示例数据到表格C for row in range(12): table_c.setItem(row, 0, QTableWidgetItem(f"2023-{row+1}-01")) table_c.setItem(row, 1, QTableWidgetItem(f"事件{row+1}")) table_c.setItem(row, 2, QTableWidgetItem("完成" if row % 2 == 0 else "进行中")) return table_c def create_table_d(self): """创建表格D""" # 创建表格D table_d = QTableWidget(6, 6) # 6行6列的表格 table_d.setHorizontalHeaderLabels(["A", "B", "C", "D", "E", "F"]) # 添加一些示例数据到表格D for row in range(6): for col in range(6): table_d.setItem(row, col, QTableWidgetItem(f"D-{row},{col}")) return table_d def setup_dock_layout(self): """设置dock widget的布局""" # 将dock_b放在dock_a下方 self.splitDockWidget(self.dock_a, self.dock_b, Qt.Vertical) # 将dock_cd放在dock_a的右边 self.splitDockWidget(self.dock_a, self.dock_cd, Qt.Horizontal) # 设置初始大小比例 self.resizeDocks([self.dock_a, self.dock_b], [200, 200], Qt.Vertical) self.resizeDocks([self.dock_a, self.dock_cd], [400, 400], Qt.Horizontal) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
代码说明
-
主要修改点:
- 将表格C和表格D的创建分别放在了两个独立的方法中:
create_table_c()和create_table_d()。 - 在
create_table_cd_dock()方法中调用这两个方法来获取表格实例。
- 将表格C和表格D的创建分别放在了两个独立的方法中:
-
模块化设计:
- 每个表格都有自己的创建方法,使代码结构更加清晰。
- 表格A和表格B的创建方法同时负责创建对应的dock widget。
- 表格C和表格D的创建方法只负责创建表格,然后由
create_table_cd_dock()方法将它们放入同一个dock widget。
-
方法职责:
create_table_c():专门负责创建和初始化表格C,返回创建好的QTableWidget实例。create_table_d():专门负责创建和初始化表格D,返回创建好的QTableWidget实例。create_table_cd_dock():负责创建包含表格C和表格D的dock widget,并设置布局。
-
布局设置:
- 保持了原有的布局设置逻辑,确保三个dock widget按照预期排列。
- 在包含表格C和表格D的dock widget内部,使用QVBoxLayout垂直排列两个表格。
-
表格数据:
- 每个表格的数据填充逻辑被封装在各自的创建方法中,使代码更加模块化。
使用示例
运行上述代码后,将显示一个包含三个dock widget的窗口:
- 左上方是包含表格A的dock widget
- 左下方是包含表格B的dock widget
- 右侧是包含表格C和表格D的dock widget,两个表格垂直排列
用户可以:
- 通过拖动dock widget的标题栏来重新排列它们
- 双击dock widget的标题栏使其浮动或重新停靠
- 点击dock widget右上角的关闭按钮暂时隐藏它
- 调整dock widget之间的分隔线来改变它们的大小
优化建议
-
表格样式统一:可以创建一个通用的表格样式设置方法,应用于所有表格,确保界面风格统一。
-
表格交互增强:为表格添加排序、筛选、搜索等功能,提高用户体验。
-
数据模型分离:使用MVC模式,将数据模型与表格视图分离,使代码更加灵活和可维护。
-
配置保存:添加功能来保存和恢复用户的布局偏好和表格设置。
-
响应式设计:优化界面在不同屏幕尺寸下的表现,确保良好的用户体验。
-
表格间数据交互:如果有需要,可以添加表格间的数据联动功能,例如点击表格A中的某行会在表格C中显示相关数据。