一、引言

在第《第三十一章、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. 【转载】使用STM8SF103 ADC采样电压

    源:使用STM8SF103 ADC采样电压 硬件环境: STM8SF103 TSSOP20封装 因为项目需要用到AD采样电池电压,于是便开始了使用STM8S ADC进行采样,也就有了下文. 手册上对S ...

  2. 1redis介绍

    一,概述 是一种nosql数据库,保存在内存中,同时redis可以把内存同时保存到磁盘,即可以把数据持久化.支持较多的数据类型,string,list(队列和栈),set,sorted set,has ...

  3. 你知道MySQL的LRU链表吗?

    相信大家对LRU链表是不陌生的,算是一种基础的数据结构! LRU:Least Recently Used 一.简述传统的LRU链表 LRU:Least Recently Used 相信大家对LRU链表 ...

  4. 手写@koa/router源码

    上一篇文章我们讲了Koa的基本架构,可以看到Koa的基本架构只有中间件内核,并没有其他功能,路由功能也没有.要实现路由功能我们必须引入第三方中间件,本文要讲的路由中间件是@koa/router,这个中 ...

  5. linux nf_conntrack 连接跟踪机制 3-hook

    conntrack hook函数分析 enum nf_ip_hook_priorities { NF_IP_PRI_FIRST = INT_MIN, NF_IP_PRI_CONNTRACK_DEFRA ...

  6. centos7安装数据库 (系统包含预装环境mariadb)

    查看系统是否安装了MySQL,有些没安装但是有路径,那是因为系统安装了mariadb-libs,对应的配置文件目录:/etc/my.cnf(下面就根据mariadb来安装mysql) 查看系统预装ma ...

  7. linux文件描述符、软硬连接、输入输出重定向

    引用链接:https://blog.csdn.net/qq769651718/article/details/79459346 文件描述符的作用: 文件描述符是linux操作系统中特有的概念.其相当于 ...

  8. 如何删除一台OSD主机

    在ceph的一台OSD主机出现故障的时候,数据可以通过副本的机制进行恢复,之后通过删除osd的操作也能够将故障osd从osd tree当中删除掉,但是故障的 osd 的主机仍然会留在集群当中,通过 c ...

  9. Nacos 多环境配置

    本文探讨Nacos作为配置中心,如何实现不同环境(开发.测试.灰度.正式)的配置管理问题 就像Maven用groupId.artifactId.version三者来定位jar包在仓库中的位置一样,Na ...

  10. POJ2689 [质数距离] 题解

    质数距离 题目TP门 题目描述 给定两个整数L和R,你需要在闭区间[L,R]内找到距离最接近的两个相邻质数C1和C2(即C2-C1是最小的),如果存在相同距离的其他相邻质数对,则输出第一对. 同时,你 ...