py demo4
February 26, 2025
PyQt5 Dock Widget 布局实现 - 参考新图片
问题分析
根据您提供的新图片,需要实现一个包含以下dock widget的布局:
- 顶部有一个横跨整个窗口的
dock_schedule - 左侧有两个垂直排列的dock widget:
dock_widget和dock2 - 右侧有一个占据右半部分的
AA_dock - 图片上还标注了"kai -> RTL",可能表示需要支持从右到左的布局方向
解决方案
我将创建一个新的布局,包含四个dock widget,按照图片所示的位置排列。
import sys from PyQt5.QtWidgets import (QApplication, QMainWindow, QDockWidget, QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget, QLabel, QCalendarWidget, QTreeWidget, QTreeWidgetItem, QListWidget, QListWidgetItem) from PyQt5.QtCore import Qt, QSize class MainWindow(QMainWindow): def __init__(self): super().__init__() # 设置窗口标题和大小 self.setWindowTitle("Dock Widget布局示例") self.setMinimumSize(1000, 700) # 创建一个透明的中央部件 central_widget = QWidget() central_widget.setMaximumSize(0, 0) # 最小化中央部件 self.setCentralWidget(central_widget) # 创建四个dock widget self.create_schedule_dock() self.create_widget_dock() self.create_dock2() self.create_aa_dock() # 设置dock widget的布局 self.setup_dock_layout() # 支持RTL布局(如果需要) # self.setLayoutDirection(Qt.RightToLeft) def create_schedule_dock(self): """创建顶部的schedule dock widget""" self.dock_schedule = QDockWidget("日程安排", self) self.dock_schedule.setObjectName("dock_schedule") self.dock_schedule.setAllowedAreas(Qt.TopDockWidgetArea | Qt.BottomDockWidgetArea) self.dock_schedule.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) # 使用日历组件作为内容 calendar = QCalendarWidget() self.dock_schedule.setWidget(calendar) # 将dock widget添加到主窗口顶部 self.addDockWidget(Qt.TopDockWidgetArea, self.dock_schedule) def create_widget_dock(self): """创建左上角的widget dock""" self.dock_widget = QDockWidget("部件列表", self) self.dock_widget.setObjectName("dock_widget") self.dock_widget.setAllowedAreas(Qt.AllDockWidgetAreas) self.dock_widget.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) # 创建一个树形部件作为内容 tree = QTreeWidget() tree.setHeaderLabels(["部件", "类型"]) # 添加一些示例数据 items = [ ("按钮", "QPushButton"), ("标签", "QLabel"), ("输入框", "QLineEdit"), ("复选框", "QCheckBox"), ("单选按钮", "QRadioButton") ] for name, type_name in items: item = QTreeWidgetItem([name, type_name]) tree.addTopLevelItem(item) self.dock_widget.setWidget(tree) # 将dock widget添加到主窗口左侧 self.addDockWidget(Qt.LeftDockWidgetArea, self.dock_widget) def create_dock2(self): """创建左下角的dock2""" self.dock2 = QDockWidget("数据列表", self) self.dock2.setObjectName("dock2") self.dock2.setAllowedAreas(Qt.AllDockWidgetAreas) self.dock2.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) # 创建一个列表部件作为内容 list_widget = QListWidget() # 添加一些示例数据 items = [ "项目 1", "项目 2", "项目 3", "项目 4", "项目 5", "项目 6", "项目 7", "项目 8" ] for item_text in items: list_widget.addItem(QListWidgetItem(item_text)) self.dock2.setWidget(list_widget) # 将dock widget添加到主窗口左侧 self.addDockWidget(Qt.LeftDockWidgetArea, self.dock2) def create_aa_dock(self): """创建右侧的AA dock""" self.aa_dock = QDockWidget("数据表格", self) self.aa_dock.setObjectName("AA_dock") self.aa_dock.setAllowedAreas(Qt.AllDockWidgetAreas) self.aa_dock.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) # 创建一个表格作为内容 table = QTableWidget(15, 5) table.setHorizontalHeaderLabels(["ID", "名称", "类别", "数量", "状态"]) # 添加一些示例数据 for row in range(15): table.setItem(row, 0, QTableWidgetItem(f"{row+1001}")) table.setItem(row, 1, QTableWidgetItem(f"产品 {row+1}")) table.setItem(row, 2, QTableWidgetItem(f"类别 {(row % 3) + 1}")) table.setItem(row, 3, QTableWidgetItem(f"{row * 5 + 10}")) table.setItem(row, 4, QTableWidgetItem("可用" if row % 2 == 0 else "缺货")) self.aa_dock.setWidget(table) # 将dock widget添加到主窗口右侧 self.addDockWidget(Qt.RightDockWidgetArea, self.aa_dock) def setup_dock_layout(self): """设置dock widget的布局,按照图片所示排列""" # 确保schedule dock横跨整个窗口顶部 self.resizeDocks([self.dock_schedule], [100], Qt.Vertical) # 将dock_widget和dock2垂直排列在左侧 self.splitDockWidget(self.dock_widget, self.dock2, Qt.Vertical) # 将aa_dock放在dock_widget的右侧 self.splitDockWidget(self.dock_widget, self.aa_dock, Qt.Horizontal) # 设置dock widget的大小比例 self.resizeDocks([self.dock_widget, self.dock2], [300, 300], Qt.Vertical) self.resizeDocks([self.dock_widget, self.aa_dock], [300, 700], Qt.Horizontal) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
代码说明
-
布局结构:
- 创建了四个dock widget,分别对应图片中的
dock_schedule、dock_widget、dock2和AA_dock。 dock_schedule横跨窗口顶部,dock_widget和dock2垂直排列在左侧,AA_dock占据右侧区域。
- 创建了四个dock widget,分别对应图片中的
-
各Dock Widget的内容:
dock_schedule:使用QCalendarWidget日历组件,适合展示日程安排。dock_widget:使用QTreeWidget树形组件,展示部件列表。dock2:使用QListWidget列表组件,展示简单的数据列表。AA_dock:使用QTableWidget表格组件,展示详细的数据表格。
-
布局设置:
- 使用
splitDockWidget()方法将dock widget分割成垂直和水平组合。 - 使用
resizeDocks()方法设置初始大小比例,确保各个dock widget大小合适。 dock_schedule被限制只能在顶部或底部区域,其他dock widget可以在任何区域。
- 使用
-
RTL支持:
- 代码中包含了支持从右到左(RTL)布局的注释行,如果需要启用RTL布局,可以取消该行的注释。
- RTL布局适用于阿拉伯语、希伯来语等从右到左书写的语言。
-
Dock Widget特性:
- 所有dock widget都设置了
setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable),允许用户移动和浮动它们,但不能关闭。 - 每个dock widget都有一个描述性标题,帮助用户识别其功能。
- 所有dock widget都设置了
使用示例
运行上述代码后,将显示一个包含四个dock widget的窗口:
- 顶部是横跨整个窗口的日程安排dock widget
- 左上方是部件列表dock widget
- 左下方是数据列表dock widget
- 右侧是占据右半部分的数据表格dock widget
用户可以:
- 通过拖动dock widget的标题栏来重新排列它们
- 双击dock widget的标题栏使其浮动或重新停靠
- 调整dock widget之间的分隔线来改变它们的大小
优化建议
-
主题支持:添加明暗主题切换功能,提高用户体验。
-
数据持久化:实现数据的保存和加载功能,使用户可以保存工作状态。
-
布局保存:添加功能来保存和恢复用户自定义的dock widget布局。
-
国际化支持:添加多语言支持,包括RTL语言的完整支持。
-
交互增强:为各个组件添加上下文菜单和快捷键,提高操作效率。
-
响应式设计:优化界面在不同屏幕尺寸下的表现,确保良好的用户体验。