一、引言

在第《第三十一章、containers容器类部件QDockWidget停靠窗功能介绍》详细介绍了QDockWidget的属性、方法和信号,并介绍了利用QMainWindow的splitDockWidget和tabifyDockWidget等方法实现基于主窗口布局的方法。本节将利用相关方法实现一个简单的人机对话应用:笨笨机器人。

二、案例介绍

2.1、功能介绍

笨笨机器人是老猿测试QDockWidget的一个测试程序,其运行界面如图所示:



可以看到,该测试程序实现了一个简单的人机对话(机器应答是在设定应答语句中随机挑选一个),可以设置对话双方的名字,可以设置聊天信息的字体和颜色。

2.2、实现思路

要实现这个简单应用,有很多种方法,本次测试是为了使用QDockWidget,因此通过QMainWindow和QDockWidget配套实现。

由于QDockWidget本身的内容区域(内容)也是一个QWidget对象,要实现在QMainWindow上放置多个停靠窗、每个停靠窗要放置对应的内容子部件对象、并对停靠窗进行排列布局操作,在Designer中进行UI设计反而比通过代码实现麻烦很多,因此整体UI布局大部分都是通过代码实现的,在Designer中只实现了昵称配置信息窗口的界面和主窗口QMainWindow的主窗口基本界面。

2.3、昵称设置窗实现

昵称设置设计界面如下:



其中两个输入框的名称分别为myName和robertName。

ui设计后将其生成代码模块文件ui_configWin.py,然后派生类,只实现构造方法,其他都不进行处理。

class configWin(ui_configWin.Ui_configWin,QtWidgets.QWidget):
def __init__(self,parent=None):
super().__init__(parent)
self.setupUi(self)

2.4、主窗口基础实现

2.4.1、ui设计界面



主窗口基本界面就是一个mainWindow,没有放置任何子部件,名称也是mainWindow,设置了标题信息为:“老猿Python:DockWidget测试 网址:https://blog.csdn.net/LaoYuanPython”。生成代码后存放在模块文件ui_mainWin.py中。

2.4.2、主窗口派生类及构造方法

主窗口派生类及构造方法代码如下:

class mainWin(QtWidgets.QMainWindow,ui_mainWin.Ui_mainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.robertColor = Qt.black #设置机器人对话字体初始颜色
self.myColor = Qt.blue #设置输入对话字体初始颜色
self.setDockNestingEnabled(True) #让主窗口支持停靠窗嵌套
w = self.takeCentralWidget() #移除中央窗口部件,请参见第三十一章的介绍 self.initDock() #进行停靠窗生成及排列
说明:
  1. 构造方法中,除了常规的UI界面类的代码外,初始化了对话文本的颜色,设置了让主窗口支持停靠窗嵌套,最后调用initDock方法进行停靠窗生成及排列;
  2. 需要关注一下setDockNestingEnabled语句,相关属性的含义可以参考《PyQt(Python+Qt)学习随笔:Qt Designer中主窗口对象dockNestingEnabled属性》。但这个属性说明的字面说明太简单,实际理解还是有些复杂。在这里通过两个截图对比说明一下:上图是主窗口允许嵌套的场景,图中所有有关闭和浮动标记的窗口都是QDockWidget对象,在允许嵌套情况下,“机器人发言字体颜色”设置窗和“本机输入发言字体颜色”两个窗口可以上下堆叠合占一个停靠位的位置。而下图是未设置dockNestingEnabled的,这两个窗口就不能纵向堆叠在一起,只能选项卡式化占用一个停靠位。



    所以嵌套是指一个停靠位的位置堆叠或水平排列了两个停靠窗,而这个位置正常情况下只能放置一个对应大小的停靠窗。
  3. takeCentralWidget作用是将主窗口中央区域部件从主窗口中移除,对象并没有删除,当中央部件没有移除时,停靠窗只能停留在中央部件四周,移除后可以停靠到整个主窗口区域,下面截图对比一下:

    同一个程序,左边是移除了中央部件,右边没有,二者的效果对比可以看出移除中央部件的效果。

    如果没有调用takeCentralWidget移除中央部件,后续调用setCentralWidget将一个停靠窗口设置为中央部件也可以实现类似的效果。

2.4.3、创建对话显示框停靠窗

对话显示框dialogDisplay 为一个QTextEdit对象,将其作为dialogDisplayDock停靠窗的内容部件,将其放置在主窗口中央部件区域。

		self.dialogDisplay = QtWidgets.QTextEdit()
self.dialogDisplayDock = QtWidgets.QDockWidget("对话记录", self)
self.dialogDisplayDock.setWidget(self.dialogDisplay)#将对话窗作为对话停靠窗的内容部件
self.setCentralWidget(self.dialogDisplayDock)

2.4.4、创建输入停靠窗

输入部件input 为一个QLineEdit对象,将其作为inputDock 停靠窗的内容部件,在代码中设置了输入部件的宽度。由于部件是代码创建,因此信号与槽方法的连接关系必须代码实现,在此将输入部件按下回车键作为消息发送的信号连接到主窗口的槽方法inputEnd。

		self.input = QtWidgets.QLineEdit()
self.input.geometry().setWidth(200)
self.input.returnPressed.connect(self.inputEnd)
self.inputDock = QtWidgets.QDockWidget("对话输入(回车键发送):", self)
self.inputDock.setWidget(self.input)#将输入部件input作为inputDock停靠窗的内容部件

2.4.5、构建字体选择停靠窗、机器人对话文本颜色停靠窗、发言人对话文本颜色停靠窗

字体选择停靠窗fontDock包含标题和一个设置字体的按钮,按钮点击后能触发字体选择。

		self.fontDock = QtWidgets.QDockWidget('字体设置',self)
fontButton = QtWidgets.QPushButton('点此设置字体',self.fontDock)
setFontSizeColor(fontButton,QtGui.QPalette.ButtonText,Qt.red,10)#设置按钮文字的颜色和大小
fontButton.clicked.connect(self.getFont)
self.fontDock.setWidget(fontButton)#将fontButton作为fontDock停靠窗的内容部件

机器人对话文本颜色停靠窗robertFontColorDock用于设置输入文字在对话窗中显示的颜色、发言人对话文本颜色停靠窗myFontColorDock用于设置机器人应答文字在对话窗中显示的颜色,二者的实现与fontDock类似,只是按钮连接的槽方法不同,设置的按钮颜色不同。在此不详细介绍,大家可参考附件代码。

2.4.6、构建昵称设置停靠窗

昵称设置停靠窗configDock包含内容部件configWin,configWin是一个单独的ui设计模块派生的类,用于设置输入者昵称和机器人昵称,其ui设计界面如下:



在构建configDock时,将configWin作为其内容部件。

2.4.7、排列停靠窗

将所有停靠窗对象及对应内容部件对象都创建后,接下来需要在QMainWindow中排列这些窗口,最终程序运行后的初始排列效果如下:

要实现停靠窗的排列,需要分如下两步进行:

2.4.7.1、将所有停靠窗按一定位置加到主窗口

按照上图的排列,dialogDisplayDock在嘴上,输入框在左边,昵称配置窗在右边,其他在最下面,按此规则使用如下语句将停靠窗加入到主窗口:

		self.addDockWidget(QtCore.Qt.TopDockWidgetArea, self.dialogDisplayDock)
self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.inputDock)
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.configDock)
self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.fontDock) self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.robertFontColorDock)
self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.myFontColorDock)
self.configDock.setMinimumWidth(320) #设置配置窗最小宽度
运行后效果:

2.4.7.2、使用splitDockWidget和tabifyDockWidget调整窗口位置

上图不是我们要的效果,此时需要使用splitDockWidget来调整这些窗口的排列。首先将昵称配置窗调整到输入框右边,然后将字体设置窗调整到输入框下边,最后将两个颜色设置框与字体设置框进行选项卡化。使用如下代码:

		self.splitDockWidget(self.inputDock, self.configDock, Qt.Horizontal) #昵称配置窗调整到输入框右边
self.splitDockWidget(self.inputDock,self.fontDock, Qt.Vertical) #将字体设置窗调整到输入框下边
self.tabifyDockWidget(self.fontDock, self.myFontColorDock) #将输入文字颜色设置框与字体设置框进行选项卡化
self.tabifyDockWidget(self.fontDock, self.robertFontColorDock) #将机器人文字颜色设置框与字体设置框进行选项卡化

大家结合上章介绍的内容理解一下splitDockWidget和tabifyDockWidget的作用。

运行效果:

发现达到了想要的效果。

2.4.8、实现对话窗发送消息后的响应槽方法inputEnd

在槽方法内需要设置输入消息的字体颜色并显示输入信息,同时调用机器人应答方法输出机器人应答消息。

    def inputEnd(self):
if self.myColor: self.dialogDisplay.setTextColor(self.myColor)
self.dialogDisplay.append(self.configWin.myName.text()+': '+ self.input.text())
self.input.clear()
self.robertAnswer() #输出机器人应答消息

2.4.9、实现设置字体的槽方法getFont

getFont方法调用字体设置对话框来获取需要设置的字体,对话框原字体作为字体设置对话窗的初始字体。

    def getFont(self):#,visible):
font = self.dialogDisplay.font() #取现有字体
font,changed = QtWidgets.QFontDialog.getFont(font,self,"字体设置") if changed: self.dialogDisplay.setFont(font)

2.4.10、实现设置输入文字或机器人应答文字颜色的槽方法getFontColor

getFontColor方法需要判断信号发射对象是来自输入文字颜色设置按钮还是机器人应答消息颜色按钮,然后根据不同取不同的初始颜色,并调用颜色选择对话窗选择颜色,并将颜色记录后,将对应按钮的文字颜色设置文新的颜色。相关代码与设置字体类似,在此就不介绍了。

经过以上步骤,一个比较完整的人机对话简单应用就构建完了。

广告

老猿关于PyQt的付费专栏《使用PyQt开发图形界面Python应用》只需要9.9元,该部分与第十五章的内容基本对应,但同样内容在付费专栏上总体来说更详细、案例更多。本节内容对应付费专栏的《第三十二章、使用splitDockWidget和tabifyDockWidget嵌套布局QDockWidget的PyQt人机对话案例》。如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。

老猿Python,跟老猿学Python!

第15.39节、splitDockWidget和tabifyDockWidget嵌套布局QDockWidget的PyQt人机对话案例:笨笨机器人的更多相关文章

  1. 第三十二章、使用splitDockWidget和tabifyDockWidget嵌套布局QDockWidget的PyQt人机对话案例

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.引言 在第<第三十一章.containers容器类部件QDo ...

  2. 第15.40节、PyQt(Python+Qt)实战:moviepy实现MP4视频转gif动图的工具

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.引言 在写<第15.39节.splitDockWidget和 ...

  3. 第15.38节 PyQt(Python+Qt)入门学习:containers容器类部件QDockWidget停靠窗功能详解

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.概述 QDockWidget类提供了一个可以停靠在QMainWin ...

  4. Android零基础入门第39节:ListActivity和自定义列表项

    原文:Android零基础入门第39节:ListActivity和自定义列表项 相信通过前两期的学习,以及会开发最简单的一些列表界面了吧,那么本期接着来学习更多方法技巧. 一.使用ListActivi ...

  5. 第15.9节 PyQt学习入门:使用Qt Designer进行GUI设计的步骤

    在使用Qt Designer进行GUI设计时,一般常规的步骤都是差不多的,主要步骤包括新建显示窗口.在窗口上按照规划的布局放置组件.设置初始化组件的属性.定义信号和槽函数的连接,一般后三步是每增加一个 ...

  6. 第15.48节、PyQt显示部件:TextBrowser、CalendarWidget、LCDNumber、ProgressBar、Label、HorizontalLine和VerticalLine简

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.概述 在Designer中,显示部件有Labe ...

  7. 第15.44节、PyQt输入部件:QAbstractSlider派生类QScrollBar滚动条、QSlider滑动条、QDial刻度盘功能详解

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.引言 Designer中的输入部件Horizo ...

  8. 第15.37节 PyQt(Python+Qt)入门学习:containers容器类部件QMdiArea多文档界面部件详解及编程开发案例

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.引言 老猿在前期学习PyQt相关知识时,对每个组件的属性及方法都研 ...

  9. 第15.30节 PyQt编程实战:通过eventFilter监视QScrollArea的widget()的Paint消息画出scrollAreaWidgetContents的范围矩形

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.引言 在<PyQt(Python+Qt)学习随笔:QScrollArea滚动区域详解> ...

随机推荐

  1. 用数组实现队列(顺序队列&循环队列)

    用数组实现队列(顺序队列&循环队列) 顺序队列 ️ 队列(先进先出) 几个问题: 队列方法:入队.出队 队列的存储:即队首队尾两个指针, 扩容:如果队列容量不够了,应该扩容,如果队尾没有位置了 ...

  2. Linux 下 GCC 的使用

    0 运行环境 本机系统:Windows 7 虚拟机软件:Oracle VM VirtualBox 6 虚拟机系统:CentOS 7 1 GCC 简介 GCC 是 GUN Compiler Collec ...

  3. springboot-rabbitmq之hello-world(一)

    概念介绍 这里引用rabbit官网的一张图 image.png 大概意思就是生产着把消息发送到队列然后消费者消费消息 springboot实现 hello-world比较简单这里直接上代码 生产者 声 ...

  4. zabbix 告警实践分享 一键实现zabbix 电话、邮件、微信告警

    众所周知Zabbix 是一款用来监控IT基础设施的监控套件,同时也具有很多方便运维人员使用的优秀功能,如:支持多条件告警,支持多种告警方式,支持多组模板.支持模板继承,因此在众多的开源运维监控软件中独 ...

  5. ASCII、Unicode、UTF-8、UTF-8(without BOM)、UTF-16、UTF-32傻傻分不清

    ASCII.Unicode.UTF-8.UTF-8(without BOM).UTF-16.UTF-32傻傻分不清 目录 ASCII.Unicode.UTF-8.UTF-8(without BOM). ...

  6. python之《set》

    set 是python里面的集合的概念 list_1 = [1,2,3,4,5,6,] list_2 = set(list_1) print(list_1,type(list_1)) print(li ...

  7. SQL Server将查询出数据进行列转行操作

    在日常的SQL Server数据查询时经常会遇到需要将数据列转换成行的操作,现将自己学习的列转行SQL语句举例如下: --首先查询语句 SELCT * FROM  YXBAK..TBYJKSTEMP ...

  8. MGR(MySQL Group Replication)部署测试

    1. 环境说明 192.168.11.131 mgr1 主节点 192.168.11.132 mgr2 从节点 192.168.11.133 mgr3 从节点 2. 在mgr1.mgr2.mgr3上安 ...

  9. ppt-1 操作界面与基本操作

    1.Ctrl+N快速建立新文档 2.新模板:文件--新建--可免费搜索.下载新模板 3.恢复未保存的演示文稿 文件--打开(首先看到的是近期使用的演示文稿,)--鼠标滚动至末尾,可看到"恢复 ...

  10. 实战教程:如何将自己的Python包发布到PyPI上

    1. PyPi的用途 Python中我们经常会用到第三方的包,默认情况下,用到的第三方工具包基本都是从Pypi.org里面下载. 我们举个栗子: 如果你希望用Python实现一个金融量化分析工具,目前 ...