py demo4

February 26, 2025

PyQt5 Dock Widget 布局实现 - 参考新图片

问题分析

根据您提供的新图片,需要实现一个包含以下dock widget的布局:

  1. 顶部有一个横跨整个窗口的dock_schedule
  2. 左侧有两个垂直排列的dock widget:dock_widgetdock2
  3. 右侧有一个占据右半部分的AA_dock
  4. 图片上还标注了"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_())

代码说明

  1. 布局结构

    • 创建了四个dock widget,分别对应图片中的dock_scheduledock_widgetdock2AA_dock
    • dock_schedule横跨窗口顶部,dock_widgetdock2垂直排列在左侧,AA_dock占据右侧区域。
  2. 各Dock Widget的内容

    • dock_schedule:使用QCalendarWidget日历组件,适合展示日程安排。
    • dock_widget:使用QTreeWidget树形组件,展示部件列表。
    • dock2:使用QListWidget列表组件,展示简单的数据列表。
    • AA_dock:使用QTableWidget表格组件,展示详细的数据表格。
  3. 布局设置

    • 使用splitDockWidget()方法将dock widget分割成垂直和水平组合。
    • 使用resizeDocks()方法设置初始大小比例,确保各个dock widget大小合适。
    • dock_schedule被限制只能在顶部或底部区域,其他dock widget可以在任何区域。
  4. RTL支持

    • 代码中包含了支持从右到左(RTL)布局的注释行,如果需要启用RTL布局,可以取消该行的注释。
    • RTL布局适用于阿拉伯语、希伯来语等从右到左书写的语言。
  5. Dock Widget特性

    • 所有dock widget都设置了setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable),允许用户移动和浮动它们,但不能关闭。
    • 每个dock widget都有一个描述性标题,帮助用户识别其功能。

使用示例

运行上述代码后,将显示一个包含四个dock widget的窗口:

  1. 顶部是横跨整个窗口的日程安排dock widget
  2. 左上方是部件列表dock widget
  3. 左下方是数据列表dock widget
  4. 右侧是占据右半部分的数据表格dock widget

用户可以:

  1. 通过拖动dock widget的标题栏来重新排列它们
  2. 双击dock widget的标题栏使其浮动或重新停靠
  3. 调整dock widget之间的分隔线来改变它们的大小

优化建议

  1. 主题支持:添加明暗主题切换功能,提高用户体验。

  2. 数据持久化:实现数据的保存和加载功能,使用户可以保存工作状态。

  3. 布局保存:添加功能来保存和恢复用户自定义的dock widget布局。

  4. 国际化支持:添加多语言支持,包括RTL语言的完整支持。

  5. 交互增强:为各个组件添加上下文菜单和快捷键,提高操作效率。

  6. 响应式设计:优化界面在不同屏幕尺寸下的表现,确保良好的用户体验。