第三十一章、containers容器类部件QDockWidget停靠窗功能介绍
一、概述
QDockWidget类提供了一个可以停靠在QMainWindow中或作为桌面上的顶级窗口浮动的部件。停靠窗口(Dock windows)是放置在QMainWindow主窗口中央窗口部件(Central widget)周围的次要窗口,如下图中央部件周围的白色区域,这块区域老猿称为停靠区域。

根据停靠窗口的属性设置,停靠窗口可以在停靠区域内移动,移动到新区域并由最终用户确定是否浮动。
QDockWidget对象由一个标题栏和内容区域组成。标题栏显示浮动窗口标题、浮动按钮(
)和关闭按钮。根据QDockWidget的设置,这两个按钮可能被禁用或根本不显示。
QDockWidget的内容区域,实际上是一个它包含的子部件,浮动窗口展示的内容即该子部件的内容,该子部件必须是QWidget或其派生类。
二、QDockWidget的重要属性及关联信号
2.1、Designer中QDockWidget的属性
在Designer中,QDockWidge有如下属性:

2.2、属性及关联信号介绍
2.2.1、floating属性
floating属性表示QDockWidget对象是否浮动在主窗口之上,如果为True表示浮动停靠部件作为漂浮在其父QMainWindow的“顶部”使用独立窗口展现,为False则停靠在在QMainWindow中。缺省为True,可通过方法isFloating()、setFloating(bool
floating)来访问该属性,当此属性改变时,会发射 topLevelChanged(bool floating) 信号,信号签名表示QDockWidget对象现状是否浮动在主窗口之上
2.2.2、features属性
features属性用于设置浮动部件的特征,其类型为枚举类型 QDockWidget.DockWidgetFeatures,特征包括浮动窗是否可关闭(DockWidgetClosable)、是否可移动(DockWidgetMovable)、是否可浮动(DockWidgetFloatable)、是否将标题栏展示在窗口左边成竖直标题栏(DockWidgetVerticalTitleBar)。除了这几个值之外,该特征类型在Designer中还有如下取值:
- AllDockWidgetFeatures:表示同时设置了DockWidgetClosable、DockWidgetMovable、DockWidgetFloatable这三个特征,但不一定设置了DockWidgetVerticalTitleBar特征,但不建议使用这个值,因为Qt或PyQt可能会增加其他特征值时,AllDockWidgetFeatures包括的特征范围可能会增加
- DockWidgetFeatureMask:表示同时设置了DockWidgetClosable、DockWidgetMovable、DockWidgetFloatable、DockWidgetVerticalTitleBar这四个特征,这个DockWidgetFeatureMask值仅在Designer中使用,选择这个特征则自动勾选上述四个特征,但在类中无此枚举值,即代码不识别该值;
- NoDockWidgetFeatures:表示不设置任何特征,在Designer中选择此值自动去掉其他特征,由于此值对应数值为0,代码中如果使用此值与其他值组合,则此值将失效,以其他值为准
- Reserved:这个值在Designer中选择后,将会勾选所有除NoDockWidgetFeatures之外的特征值,但该值在代码中无效。
features属性缺省为 DockWidgetClosable, DockWidgetMovable和DockWidgetFloatable的组合,可通过方法features() 和setFeatures(DockWidgetFeatures features)访问该属性。
当features属性修改时,会发射featuresChanged(QDockWidget.DockWidgetFeatures features)信号。
注意:
- 当floating为True,而features属性未设置为可浮动(DockWidgetFloatable)时,浮动窗是浮动状态,但一旦停靠后就不能通过手工操作将其再浮动起来
2.2.3、allowedAreas属性
allowedAreas属性用于控制停靠部件在QMainWindow的停靠区域中可停靠的范围,其类型为枚举类型Qt.DockWidgetArea或其值的组合,分别控制可以停靠在主窗口停靠区域的左边(LeftDockWidgetArea)、右边(RightDockWidgetArea)、顶部(TopDockWidgetArea)、底部(BottomDockWidgetArea)、所有区域(AllDockWidgetAreas)和不能停靠(NoDockWidgetArea)。
allowedAreas属性缺省值为AllDockWidgetAreas,即所有区域都可以停靠,可以通过allowedAreas()和setAllowedAreas(Qt.DockWidgetAreas areas)来访问该属性。
allowedAreas属性发生变更时,QDockWidget会发射allowedAreasChanged(Qt.DockWidgetAreas allowedAreas)信号。
注意:
当allowedAreas设置为不能停靠(NoDockWidgetArea),经验证测试:
- 当Designer中docked属性设置为True时,此时通过鼠标拖拽停靠窗在停靠区域移动不能将停靠处自动停靠,但可以双击停靠处标题栏实现按Designer中的属性dockWidgetArea指定位置停靠。如果设置了该停靠窗是可浮动的,停靠后还可以浮动起来
- 当Designer中docked属性设置为False时,该停靠窗不但拖拽不能停靠,鼠标双击标题栏也不能停靠,而是关闭了该停靠窗
2.2.4、dockWidgetArea和docked属性
dockWidgetArea和docked属性这两个属性在Designer中有设置,dockWidgetArea表示部件的初始停靠位置,取值范围和allowedAreas相同,docked为布尔值,表示是否启用停靠功能,但这两个属性QDockWidget都没有,实际上是用于控制调用QMainWindow的addDockWidget方法,当docked为True时,Designer生成的代码就会调用QMainWindow的addDockWidget方法,addDockWidget第一个参数即为Designer属性的dockWidgetArea,当docked为False时,Designer生成的代码就不会调用QMainWindow的addDockWidget方法。
注意当docked为True时:
- 当allowedAreas设置为不能停靠(NoDockWidgetArea)时,无论dockWidgetArea设置为何值,设置后在Designer中都会自动恢复为上次allowedAreas不为不能停靠(NoDockWidgetArea)时dockWidgetArea设定的值;
- 当allowedAreas设置为AllDockWidgetAreas所有区域都可以停靠时,如果此时设置dockWidgetArea为NoDockWidgetArea、AllDockWidgetAreas、DockWidgetFeatureMask三个中的任意一个时,Designer会将allowedAreas自动修改为最近设置的LeftDockWidgetArea、RightDockWidgetArea、TopDockWidgetArea、BottomDockWidgetArea中的一个,即allowedAreas不允许设置为NoDockWidgetArea、AllDockWidgetAreas、DockWidgetFeatureMask,强行设置会自动修订到设置前的值
三、QDockWidget的其他重要方法
除了与属性相关的方法外,QDockWidget还有几个比较重要的方法。
3.1、isAreaAllowed方法
isAreaAllowed方法用于判断QMainWindow的某个停靠区域是否允许停靠,调用语法如下:
bool isAreaAllowed(Qt.DockWidgetArea area)
3.2、setTitleBarWidget方法
setTitleBarWidget方法用于给停靠窗口设置个性化的标题栏,调用语法如下:
setTitleBarWidget(QWidget widget)
说明:
- widget参数可以是任意一个QWidget 或其派生类对象,如果传None,则将原来通过setTitleBarWidget设置的部件取消了,使用缺省的窗口标题代替
- 如果设置了一个有效的QWidget 或其派生类对象作为标题栏,在浮动时不会使用本机窗口装饰(包括关闭按钮),而是使用参数部件作为标题
- 如果无法直接删除浮动窗口的标题栏,可以使用QWidget()不带参数方式构建一个QWidget对象实现相同的效果
- 使用titleBarWidget()方法可以返回该停靠窗口使用的标题栏部件。
示例代码:
self.robertFontColorDock = QtWidgets.QDockWidget('机器人发言字体颜色',self)
colorButton = QtWidgets.QPushButton('设置机器人文字颜色', self.robertFontColorDock)
self.robertFontColorDock.setWidget(colorButton)
self.robertFontColorDock.setFeatures(QtWidgets.QDockWidget.NoDockWidgetFeatures|QtWidgets.QDockWidget.DockWidgetFloatable)
self.robertFontColorDock.setTitleBarWidget(configWin(self))
3.3、widget和setWidget方法
在概述部分介绍了,QDockWidget对象由一个标题栏和内容区域组成。QDockWidget的内容区域,实际上是一个它包含的子部件,浮动窗口展示的内容即该子部件的内容,该子部件必须是QWidget或其派生类。方法widget和setWidget就是用于访问QDockWidget的内容区域对应的子部件。调用语法如下:
setWidget(QWidget widget)QWidget widget()
注意:
- 如果QDockWidget已经可见后再调用setWidget设置内容部件,则必须调用内容部件的show()方法才能看到该部件的内容
- 官方文档说,在调用setWidget方法前,参数widget对应部件必须设置了布局,否则该widget对应部件不可见,但老猿测试未设置布局也没有问题。
3.4、toggleViewAction方法
toggleViewAction方法返回一个动作对象,该动作对象通过点击后可以切换停靠窗口的可见状态,即该动作是一个对停靠部件窗口显示或关闭的开关,如果将该动作加到菜单上,对应菜单栏的文字即为停靠窗口的title文字,这样就可以在菜单上点击对应菜单项进行停靠窗口的关闭和显示,这个关闭和显示的状态在QMainWindow的快捷菜单中就有这样的功能。下图是QMainWindow的停靠窗口开关状态快捷菜单以及将部分停靠窗口(字体设置、机器人发言字体颜色、本机输入发言字体颜色)对应开关动作加到菜单栏的一个案例截图:

上图中有2个停靠窗口是关闭的,如果所有停靠窗全部显示则如下效果:

上图中黄色标记的标签选项栏对应三个停靠窗。
示例代码
a = dock.toggleViewAction()
m = self.menuBar()
m.addAction(a)
四、QDockWidget的信号
除了前面介绍属性的时候介绍的信号allowedAreasChanged、featuresChanged、topLevelChanged外,QDockWidget还有2个信号:dockLocationChanged、visibilityChanged。
dockLocationChanged信号在QDockWidget停靠位置因手工拖拽或代码执行导致停靠位置发生变化时发射,包括移动到不同停靠区域或同一停靠区域的不同位置都会发射该信号。信号语法:dockLocationChanged(Qt.DockWidgetArea area)
visibilityChanged信号在QDockWidget可见状态发生变化时发射,这种可见状态发生变化包括显示或隐藏窗口以及QDockWidget对象停靠在选项卡区域时QDockWidget对象对应选项被选中或去选中时。信号语法:visibilityChanged(bool visible)
五、QMainWindow与QDockWidget相关的操作方法以及信号
5.1、引言
QDockWidget除了放在QMainWindow窗口内外,也可以放在其他类型的窗体如QWidget窗口内,但QMainWindow提供了与QDockWidget配套的特性如停靠区域,而其他窗口没有配套特性,QDockWidget在其他窗口中也可以浮动,但拖拽时无法自动停靠,只能通过鼠标双击标题栏回到原始位置。
QMainWindow与QDockWidget相关的特性处理停靠区域的支持外,还提供了与停靠窗口相关的:
- 三个属性:animated、dockNestingEnabled、dockOptions
- 八个方法:addDockWidget、dockWidgetArea、removeDockWidget、resizeDocks、restoreDockWidget、splitDockWidget、tabifiedDockWidgets、tabifyDockWidget
- 一个信号:tabifiedDockWidgetActivated
其中三个属性已经在《第十一章、Designer中主窗口QMainWindow类》进行了介绍,在此不重复介绍。
5.2、addDockWidget方法
QMainWindow的addDockWidget方法用于将对应停靠窗增加到指定区域,调用语法如下:
- addDockWidget(Qt.DockWidgetArea area, QDockWidget dockwidget)
- addDockWidget(Qt.DockWidgetArea area, QDockWidget dockwidget, Qt.Orientation orientation)
参数area用于指定QDockWidget对象的初始停靠区域,orientation确认标题栏是位于顶部水平方向,还是位于左边竖直方向。
经老猿验证发现:
- 如果addDockWidget的floating属性是True,则停靠窗会漂浮在主窗口上面,但当双击停靠窗标题栏时就会将该停靠窗停靠到参数area指定区域;
- addDockWidget的area参数不是总会起作用,要具体看看QDockWidget对象的大小以及当前主窗口的其他QDockWidget对象的排列情况,如一个比较大的浮动窗是不能放置在左边或右边区域,只能在顶部和底部区域;
- 如果一个QDockWidget对象未调用addDockWidget添加到主窗口中,则在主窗口的快捷菜单中无法看到该QDockWidget对象,也不能双击鼠标将该停靠窗由浮动改为驻留状态;
4.addDockWidget可以重复调用,后续调用将改变前面调用的效果,即该方法不但可以将浮动窗口增加到主窗口对应浮动区域中,而且还可以用来改变浮动窗的浮动位置和标题栏方向 。
5.3、resizeDocks
resizeDocks用于将QMainWindow的多个停靠窗的大小进行调整,调用语法如下:
resizeDocks( Iterable[QDockWidget], Iterable[int], Qt.Orientation)
参数说明:
- Iterable[QDockWidget]:需要调整的多个停靠窗对象组成的迭代类型如列表
- Iterable[int]:每个停靠窗需要调整的宽度或高度
- Qt.Orientation:调整的是宽度还是高度,如果为Qt.Horizontal,调整宽度,否则调整高度
注意:
- 大小的调整受最小和最大大小的约束
- 大小调整不会影响主窗口的大小
- 如果空间有限的情况下,调整时根据各个停靠窗口的相对大小占比进行可以利用空间的调整
5.4、tabifyDockWidget
主窗口的tabifyDockWidget方法用于将主窗口的两个停靠窗口创建一个选项卡式的停靠区域。调用语法:
tabifyDockWidget(QDockWidget first, QDockWidget second)
该方法将将second停靠窗移动到first停靠窗的顶部,在主窗口中创建一个选项卡式停靠区域。如图:

上图荧光笔标记部分为选项卡,蓝色标记部分为停靠窗的内容区域,二者加起来就是一个选项卡式停靠区域,两个停靠窗可以点击下面的选项卡切换。
5.5、splitDockWidget
主窗口的splitDockWidget方法用于将一个停靠窗占据的空间分割成两部分,原有停靠窗放置在第一部分的区域,另一个停靠窗放置在第二部分的区域。调用语法:
splitDockWidget( QDockWidget first, QDockWidget second, Qt.Orientation orientation)
说明:
- orientation:指定分割方向,是水平分隔还是垂直分隔,如果水平分隔,则这两个停靠窗水平方向并列,first在左second在右,如果是垂直分隔,则两个停靠窗上下排列,first在上second在下
- 如果第一个停靠窗已经是选项卡化停靠窗,则第二个停靠窗将作为新选项卡添加,而不是作为第一个的邻居,这是因为单个选项卡只能包含一个停靠部件,此时splitDockWidget的效果与tabifyDockWidget效果相同
- splitDockWidget实际使用时更多的是用于排列相关停靠窗口使用,也即对停靠窗口通过代码进行排列调整
案例:
要将ui设计的一个如下垂直布局的主窗口界面:

上面ui中用了三个停靠窗,从上到下分别为d3、d2、d1。如果将它们排列成一个如下的界面:

代码如下:
self.addDockWidget(QtCore.Qt.TopDockWidgetArea, self.d1)
self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.d2)
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.d3)
如果要将其设计成一个如下运行的界面:

代码如下:
self.addDockWidget(QtCore.Qt.TopDockWidgetArea, self.d1)
#self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.d2)
#self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.d3)
self.splitDockWidget(self.d1, self.d2,Qt.Vertical)
self.splitDockWidget(self.d2,self.d3,Qt.Horizontal)
注意:上面代码中注释的语句与不注释效果一样。
上面两种不同的界面效果,第一个因为没有采用分隔排列,但d2、d3分别放置在左边和右边,由于布局的缘故,占了下面所有的空间,而第二种方式采用了分割,d3分割了d2的空间,因此二者没有占满整个主窗口的空间。
其实上面两个例子还不能完整体现splitDockWidget的作用,因为停靠窗少了点,如果停靠窗很多,排列更复杂的排列,就能发挥splitDockWidget的功用。
5.6、其他方法简介
QMainWindow的其他4个与QDockWidget相关的方法dockWidgetArea、removeDockWidget、 restoreDockWidget、tabifiedDockWidgets功能非常简单:
- Qt.DockWidgetArea dockWidgetArea(QDockWidget dockwidget)
用于返回dockwidget停靠窗的停靠区,如果dockwidget未加到主窗口中,则返回Qt.NoDockWidgetArea。 - removeDockWidget(QDockWidget dockwidget)
用于将主窗口中的停靠窗dockwidget移除并隐藏它,但dockwidget对象并未释放,还可以继续使用 - bool restoreDockWidget(QDockWidget dockwidget)
将dockwidget恢复成初始创建状态,成功返回True,否则返回False。 - list[QDockWidget] tabifiedDockWidgets(QDockWidget dockwidget)
返回与参数dockwidget指定停靠窗一起成选项卡式排列的所有停靠窗列表。
5.7、tabifiedDockWidgetActivated信号
tabifiedDockWidgetActivated信号为主窗口中的选项卡式排列的停靠窗被选中激活时发射,被激活的停靠窗为信号签名参数。语法如下:
QMainWindow.tabifiedDockWidgetActivated(QDockWidget dockWidget)
六、小结
本章节详细介绍了QDockWidget的属性、方法、信号以及主窗口与QDockWidget相关的属性、方法和信号,由于主窗口提供了对停靠窗口丰富的支撑能力,才使得通过主窗口可以构建友好的用户界面。

老猿Python,跟老猿学Python!
第三十一章、containers容器类部件QDockWidget停靠窗功能介绍的更多相关文章
- 第15.38节 PyQt(Python+Qt)入门学习:containers容器类部件QDockWidget停靠窗功能详解
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.概述 QDockWidget类提供了一个可以停靠在QMainWin ...
- 第15.33节 PyQt(Python+Qt)入门学习:containers容器类部件QTabWidget选项窗部件简介
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 容器部件就是可以在部件内放置其他部件的部件,在Qt Designer中可以使用的容器部件有 ...
- 第二十七章、containers容器类部件QTabWidget选项窗部件详解
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 容器部件就是可以在部件内放置其他部件的部件,在Qt Designer中可以使用的容器部件有 ...
- 第三十章、containers容器类部件QMdiArea多文档界面部件功能介绍及开发应用
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.引言 老猿在前期学习PyQt相关知识时,对每个组件的属性及方法都研 ...
- 第15.37节 PyQt(Python+Qt)入门学习:containers容器类部件QMdiArea多文档界面部件详解及编程开发案例
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.引言 老猿在前期学习PyQt相关知识时,对每个组件的属性及方法都研 ...
- 第15.36节 PyQt(Python+Qt)入门学习:containers容器类部件QFrame框架部件介绍
一.概述 容器部件就是可以在部件内放置其他部件的部件,在Qt Designer中可以使用的容器部件有如下: 容器中的Frame为一个矩形的框架对象,对应类QFrame,QFrame类是PyQt中带框架 ...
- 第15.34节 PyQt(Python+Qt)入门学习:containers容器类部件QStackedWidget堆叠窗口部件详解
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 StackedWidget堆叠窗口部件为一系列窗口部件的堆叠,对应类为QStackedWi ...
- 第15.32节 PyQt(Python+Qt)入门学习:containers容器类部件QToolBox工具箱介绍及使用案例
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 容器部件就是可以在部件内放置其他部件的部件,在Qt Designer中可以使用的容器部件有 ...
- 第15.31节 PyQt(Python+Qt)入门学习:containers容器类部件GroupBox分组框简介
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 容器部件就是可以在部件内放置其他部件的部件,在Qt Designer中可以使用的容器部件有 ...
随机推荐
- learning to Estimate 3D Hand Pose from Single RGB Images论文理解
持续更新...... 概括:以往很多论文借助深度信息将2D上升到3D,这篇论文则是想要用网络训练代替深度数据(设备成本比较高),提高他的泛性,诠释了只要合成数据集足够大和网络足够强,我就可以不用深度信 ...
- PHP直播平台源码搭建教程
直播源码市场火爆,但是PHP直播平台源码的搭建过程较为复杂,本文就简单为大家概述一下直播的实现过程以及PHP直播平台源码是如何搭建的. 一.直播的定义 如今PHP直播平台源码绝大部分情况下是指在现场架 ...
- 用微信小程序做一个小电商 sku
效果展示图 功能点概述 图一功能点有 搜索 轮播图 商品展示 图二功能点 导航栏 加入购物车 图四功能点 评论点 图五购物车 复选框 ( 全选全不选 ) 即点即改 总计结算 功能详解 1.A(搜索) ...
- leetcode45:maximum depth of binary tree
题目描述 求给定二叉树的最大深度, 最大深度是指树的根结点到最远叶子结点的最长路径上结点的数量. Given a binary tree, find its maximum depth. The ma ...
- 03 . Vue基础之计算属性,组件基础定义和使用
vue组件 fetch请求组件 fetch XMLHttpRequest是一个设计粗糙的API, 配置和调用方式非常混乱,而且基于事件的异步模型写起来不友好,兼容性不好. <!DOCTYPE h ...
- 思科ASA放行主/被动FTP
实验环境: 设备说明: internet是一台windows10,用于模拟外网客户 ASA是思科ASA防火墙 FTP-SERVER是Centos7,Centos7上安装了vsftpd 实验说明: 本文 ...
- .net core 消息流处理流程
前言 2020年即将进入尾声,分享一下在现公司业务处理流程,一起讨论在分布式场景下,如何通过消息流的方式处理各种复杂的业务场景,这里涉及到一些常用组件,后面结合场景与代码来具体说明 场景说明 这里就拿 ...
- 面试常问的 25+ 个 Linux 命令
作为一个Java开发人员,有些常用的Linux命令必须掌握.即时平时开发过程中不使用Linux(Unix)或者mac系统,也需要熟练掌握Linux命令.因为很多服务器上都是Linux系统.所以,要和服 ...
- 微软面试题: LeetCode 4. 寻找两个正序数组的中位数 hard 出现次数:3
题目描述: 给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2.请你找出并返回这两个正序数组的中位数. 进阶:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决 ...
- ASP.NET Core管道详解[2]: HttpContext本质论
ASP.NET Core请求处理管道由一个服务器和一组有序排列的中间件构成,所有中间件针对请求的处理都在通过HttpContext对象表示的上下文中进行.由于应用程序总是利用服务器来完成对请求的接收和 ...