本文学习《PySide6/PyQt6快速开发与实践》一书,摘其中内容予以记录,及对其中代码进行验证和注释说明,进行学习,特此说明。
QDockWidget是一个可以停靠在QMainWindow内的窗口控件,可以保持浮动状态或在指定位置作为子窗口附加在主窗口中。QMainWindow主窗口中保留了一个用于停靠窗口的区域,这个区域在控件的中央区域。
个人笔记:QMainWindow类是一个特殊的QWidget窗口类,使用Qt Designer工具创建QMainWindow窗口,可以看到默认附带了菜单、工具栏、状态栏这几个标准的主窗口控件,菜单和工具栏默认在顶部,状态栏在窗口底部,中央区域可以添加其他窗口和布局对象。
QDockWidget控件由标题栏和内容区域组成。标题栏显示停靠QWidget标题、浮动按钮和关闭按钮。根据QDockWidget的状态,浮动按钮和关闭按钮可能被禁用或根本不显示。
停靠窗口可以在其当前区域内移动或者移动到新区域,也可以浮动(如取消停靠)。QDockWidget的相关函数可以限制停靠窗口移动、浮动和关闭的能力,以及允许放置的区域。
标题栏和按钮的视觉外观取决于使用的样式,各系统有其默认的样式。
QDockWidget使用setWidget()函数添加子窗口。作为子窗口的包装器,请在子窗口上自定义sizehints、minimum、maximum sizes 和sizepolices,QDockWidget会尊重子窗口的这些设置,调整自己的约束以包含框架和标题。不应该在QDockWidget上设置大小约束,因为它们会根据悬浮状态而改变。
QDockWidget控件在主窗口内可以移动到新的区域。常用的函数如下:
setWidget() -----在Dock窗口区域设置QWidget
setFloating()-----设置窗口是否可以浮动,如果设置为True,则表示可以浮动
setAllowedAreas()---设置窗口可以停靠的区域(顶部,左侧,右侧,底部,所有,不显示)
setFeatures()----设置停靠窗口的功能属性(可关闭,可移动,可漂浮)
下面是一个完整的例子代码:
import sys
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
class DockWidgetDemo(QMainWindow):
def __init__(self, parent=None):
super(DockWidgetDemo, self).__init__(parent)
layout = QHBoxLayout()
bar = self.menuBar()
file = bar.addMenu("&File")
file.addAction("&New")
file.addAction("&Save")
file.addAction("&Quit")
self.textEdit = QTextEdit()
self.setCentralWidget(self.textEdit)
self.setLayout(layout)
self.setWindowTitle("QDockWidget例子")
self.createDock1Window()
self.createDock2Window()
self.createDock3Window()
self.createDock4Window()
self.createDock5Window()
file.triggered.connect(lambda x:self.textEdit.insertPlainText(f'\n点击了菜单:{x.text()}'))
self.textEdit.clear()
def createDockWidget(self, title='', n=1):
dockWidget = QDockWidget(title, self)
listWidget = QListWidget()
listWidget.addItem(f"dock{n}-item1")
listWidget.addItem(f"dock{n}-item2")
listWidget.addItem(f"dock{n}-item3")
listWidget.currentTextChanged.connect(lambda x: self.textEdit.insertPlainText(f'\n点击了{x}'))
dockWidget.setWidget(listWidget)
dockWidget.dockLocationChanged.connect(lambda x: self.textEdit.insertPlainText(f'\ndockLocationChanged信号:{x}'))
dockWidget.featuresChanged.connect(lambda x: self.textEdit.insertPlainText(f'\nfeaturesChanged信号:{x}'))
dockWidget.topLevelChanged.connect(lambda x: self.textEdit.insertPlainText(f'\ntopLevelChanged信号:{x}'))
return dockWidget
def createDock1Window(self):
dockWidget1 = self.createDockWidget(title="Dockable1-默认", n=1)
self.addDockWidget(Qt.RightDockWidgetArea, dockWidget1)
def createDock2Window(self):
dockWidget2 = self.createDockWidget(title="Dockable2-限制停靠区域:右|下", n=2)
dockWidget2.setAllowedAreas(Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea)
self.addDockWidget(Qt.RightDockWidgetArea, dockWidget2)
def createDock3Window(self):
dockWidget3 = self.createDockWidget(title="Dockable3-浮动", n=3)
dockWidget3.setFloating(True)
self.addDockWidget(Qt.RightDockWidgetArea, dockWidget3)
def createDock4Window(self):
dockWidget4 = self.createDockWidget(title="Dockable4-关闭/移动/左侧栏", n=4)
self.addDockWidget(Qt.LeftDockWidgetArea, dockWidget4)
dockWidget4.setFeatures(QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetMovable|QDockWidget.DockWidgetVerticalTitleBar)
def createDock5Window(self):
dockWidget5 = self.createDockWidget(title="Dockable5-修改自定义标题", n=5)
self.addDockWidget(Qt.LeftDockWidgetArea, dockWidget5)
dockWidget5.setTitleBarWidget(QLabel('Dockable5-使用自定义标题',self))
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = DockWidgetDemo()
demo.show()
sys.exit(app.exec())
运行代码,显示如下窗口,如下:
上面代码创建了5个Dock窗口,下面分别进行介绍:
1)标准dock窗口+信号和槽
QDockWidget作为一个容器,使用setWidget()函数添加子窗口。当dock窗口的位置发生变化时会触发dockLocationChangeed信号,feature发生变化时会触发featureChanged信号,浮动状态发生变化是会触发topLevelChanged信号。使用addDockWidget()函数可以新增dock窗口,这里默认添加到右侧。默认情况下,dock窗口可关闭、可移动、可浮动,非常灵活,可以通过一些设置限制默认窗口的行为,代码如下:
# 定义一个创建浮动窗口控件的函数
def createDockWidget(self,title='',n=1):
# 创建一个dock窗口实例对象
# 实例化QDockWidget()中传入参数self,为其指定父窗口,父窗口关闭,将此窗口的内存也清除
dockWidget = QDockWidget(title,self)
# 创建一个QListWidget控件对象,并添加3个项目
listWidget = QListWidget()
listWidget = QListWidget()
listWidget.addItem(f"dock{n}-item1")
listWidget.addItem(f"dock{n}-item2")
listWidget.addItem(f"dock{n}-item3")
# 设置listWidget的槽函数
listWidget.currentTextChanged.connect(lambda x:self.textEdit.insertPlainText(f'\n单击了{x}')
# 把listWidget控件添加到dock窗口中
dockWidget.setWidget(listWidget)
# 设置dock窗口的信号及槽函数处理
dockWidget.dockLocationChanged.connect(lambda x:self.textEdit.insertPlainText(f'\ndockLocalChange信号:{x}'))
# 设置其它信号
return dockWidget
# 定义创建一个浮动窗口控件,添加到主窗口中
def createDock1Window(self):
dockWidget1 = self.createDockWidget(title="Dockable1-默认", n=1)
self.addDockWidget(Qt.RightDockWidgetArea, dockWidget1)
2)限制dock窗口控件的停靠区域
使用setAllowedArea()函数可以限制停靠区域,下面代码演示停靠在右侧和底部:
# 使用上面创建浮动窗口的函数创建一个浮动窗口,设置其停靠区域
def createDock2Window(self):
# 使用上面演示代码创建浮动窗口
dockWidget2 = self.createDockWidget(title="Dockable2-限制停靠区域:右|下", n=2)
# 设置停靠区域:右侧和底部
dockWidget2.setAllowedAreas(Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea)
# 添加到主窗口
self.addDockWidget(Qt.RightDockWidgetArea, dockWidget2)