第三十一章、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确认标题栏是位于顶部水平方向,还是位于左边竖直方向。

经老猿验证发现:
  1. 如果addDockWidget的floating属性是True,则停靠窗会漂浮在主窗口上面,但当双击停靠窗标题栏时就会将该停靠窗停靠到参数area指定区域;
  2. addDockWidget的area参数不是总会起作用,要具体看看QDockWidget对象的大小以及当前主窗口的其他QDockWidget对象的排列情况,如一个比较大的浮动窗是不能放置在左边或右边区域,只能在顶部和底部区域;
  3. 如果一个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功能非常简单:

  1. Qt.DockWidgetArea dockWidgetArea(QDockWidget dockwidget)
    用于返回dockwidget停靠窗的停靠区,如果dockwidget未加到主窗口中,则返回Qt.NoDockWidgetArea。
  2. removeDockWidget(QDockWidget dockwidget)
    用于将主窗口中的停靠窗dockwidget移除并隐藏它,但dockwidget对象并未释放,还可以继续使用
  3. bool restoreDockWidget(QDockWidget dockwidget)
    将dockwidget恢复成初始创建状态,成功返回True,否则返回False。
  4. list[QDockWidget] tabifiedDockWidgets(QDockWidget dockwidget)
    返回与参数dockwidget指定停靠窗一起成选项卡式排列的所有停靠窗列表。

5.7、tabifiedDockWidgetActivated信号

tabifiedDockWidgetActivated信号为主窗口中的选项卡式排列的停靠窗被选中激活时发射,被激活的停靠窗为信号签名参数。语法如下:
QMainWindow.tabifiedDockWidgetActivated(QDockWidget dockWidget)

六、小结

本章节详细介绍了QDockWidget的属性、方法、信号以及主窗口与QDockWidget相关的属性、方法和信号,由于主窗口提供了对停靠窗口丰富的支撑能力,才使得通过主窗口可以构建友好的用户界面。

老猿Python,跟老猿学Python!

原文地址:https://www.cnblogs.com/LaoYuanPython/p/12634949.html