python GUI库图形界面开发之PyQt5结合Qt Designer创建信号与槽的详细方法与实例


Posted in Python onMarch 08, 2020

在下面这3篇文章中我们给出了手工输入代码的信号与槽的使用方法,因为采用这种方法介绍时,会简单一些,如果使用Qt Designer来介绍这些功能,那么任何一个简单的功能都会使用xxxx.ui xxxx.py call_xxxx.py三个文件 来实现,这样内容会显得很乱

在实战应用中,由于Qt Designer可以很好的实现界面显示与业务逻辑分离,所有能保住我们解决大量的代码,如果能够使用Qt Designer自动创建一些信号与槽机制,那就更好了。

本例要实现的功能是:通过一个模拟打印的界面来详细说明信号的使用,在打印时,可以设置打印的份数,纸张类型,触发打印按钮后,将执行结果显示在右侧,通过QCheckBox(全屏预览 复选框)来选择是否通过全屏模式进行预览,将执行结果显示在右侧

按F1键可以显示helpmessage帮助信息

第一步:Qt Designer

首先,使用Qt Designer新建一个模板名为widget的简单窗口,通过将widget box区域的控件拖曳到窗口中,实现如图的界面效果

python GUI库图形界面开发之PyQt5结合Qt Designer创建信号与槽的详细方法与实例

这里对窗口控件进行简要说明

控件类型 控件名称 作用
QSpinBox numberSpinBox 显示打印的分数
QComboBox styleCombo 显示打印的纸张类型,纸张类型包括A3,A4等
QPushButton printButton 连接emitPrintSiagnal函数的绑定,触发自定义信号printSignal的发射
QCheckBox prievewState 是否全屏预览
QPushButton priviewButton 连接emitPreviewSignal函数的绑定,触发自定义信号previewSignal的发射
QLabel resultLabel 显示执行结果

第二步:将界面文件ui转换为py文件

pyuic5 -o xxxxx.py xxxxx.ui

会在界面文件同级目录下生成一个py文件

查看所生成的.py文件,完整代码如下

# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'MainWinSignalSlog02.ui'
#
# Created by: PyQt5 UI code generator 5.8.1
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
  def setupUi(self, Form):
    Form.setObjectName("Form")
    Form.resize(715, 225)
    self.controlsGroup = QtWidgets.QGroupBox(Form)
    self.controlsGroup.setGeometry(QtCore.QRect(10, 20, 451, 151))
    self.controlsGroup.setObjectName("controlsGroup")
    self.widget = QtWidgets.QWidget(self.controlsGroup)
    self.widget.setGeometry(QtCore.QRect(10, 40, 411, 30))
    self.widget.setObjectName("widget")
    self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget)
    self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
    self.horizontalLayout.setObjectName("horizontalLayout")
    self.label = QtWidgets.QLabel(self.widget)
    self.label.setObjectName("label")
    self.horizontalLayout.addWidget(self.label)
    self.numberSpinBox = QtWidgets.QSpinBox(self.widget)
    self.numberSpinBox.setObjectName("numberSpinBox")
    self.horizontalLayout.addWidget(self.numberSpinBox)
    self.styleCombo = QtWidgets.QComboBox(self.widget)
    self.styleCombo.setObjectName("styleCombo")
    self.styleCombo.addItem("")
    self.styleCombo.addItem("")
    self.styleCombo.addItem("")
    self.horizontalLayout.addWidget(self.styleCombo)
    self.label_2 = QtWidgets.QLabel(self.widget)
    self.label_2.setObjectName("label_2")
    self.horizontalLayout.addWidget(self.label_2)
    self.printButton = QtWidgets.QPushButton(self.widget)
    self.printButton.setObjectName("printButton")
    self.horizontalLayout.addWidget(self.printButton)
    self.widget1 = QtWidgets.QWidget(self.controlsGroup)
    self.widget1.setGeometry(QtCore.QRect(10, 100, 201, 30))
    self.widget1.setObjectName("widget1")
    self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget1)
    self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
    self.horizontalLayout_2.setObjectName("horizontalLayout_2")
    self.previewStatus = QtWidgets.QCheckBox(self.widget1)
    self.previewStatus.setObjectName("previewStatus")
    self.horizontalLayout_2.addWidget(self.previewStatus)
    self.previewButton = QtWidgets.QPushButton(self.widget1)
    self.previewButton.setObjectName("previewButton")
    self.horizontalLayout_2.addWidget(self.previewButton)
    self.resultGroup = QtWidgets.QGroupBox(Form)
    self.resultGroup.setGeometry(QtCore.QRect(470, 20, 231, 151))
    self.resultGroup.setObjectName("resultGroup")
    self.resultLabel = QtWidgets.QLabel(self.resultGroup)
    self.resultLabel.setGeometry(QtCore.QRect(20, 30, 191, 101))
    self.resultLabel.setObjectName("resultLabel")
    self.retranslateUi(Form)
    QtCore.QMetaObject.connectSlotsByName(Form)
  def retranslateUi(self, Form):
    _translate = QtCore.QCoreApplication.translate
    Form.setWindowTitle(_translate("Form", "打印控件"))
    self.controlsGroup.setTitle(_translate("Form", "打印控制"))
    self.label.setText(_translate("Form", "打印份数:"))
    self.styleCombo.setItemText(0, _translate("Form", "A3"))
    self.styleCombo.setItemText(1, _translate("Form", "A4"))
    self.styleCombo.setItemText(2, _translate("Form", "A5"))
    self.label_2.setText(_translate("Form", "纸张类型:"))
    self.printButton.setText(_translate("Form", "打印"))
    self.previewStatus.setText(_translate("Form", "全屏预览"))
    self.previewButton.setText(_translate("Form", "预览"))
    self.resultGroup.setTitle(_translate("Form", "操作结果"))
    self.resultLabel.setText(_translate("Form", "<html><head/><body><p><br/></p></body></html>"))

第三步:新建调用窗口

为了使窗口的显示与业务逻辑分离,在建一个调用窗口显示的文件,在调用类中添加多个自定义信号,并与槽函数进行绑定,其完整代码如下

# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from jia_07 import Ui_Form
from PyQt5.QtCore import pyqtSignal, Qt
class MyMainWindow(QMainWindow, Ui_Form):
  helpSignal = pyqtSignal(str)
  printSignal = pyqtSignal(list)
  # 声明一个多重载版本的信号,包括了一个带int和str类型参数的信号,以及带str参数的信号
  previewSignal = pyqtSignal([ int, str ], [ str ])
  def __init__( self, parent=None ):
    super(MyMainWindow, self).__init__(parent)
    self.setupUi(self)
    self.initUI()
  def initUI( self ):
    self.helpSignal.connect(self.showHelpMessage)
    self.printSignal.connect(self.printPaper)
    self.previewSignal[ str ].connect(self.previewPaper)
    self.previewSignal[ int, str ].connect(self.previewPaperWithArgs)
    self.printButton.clicked.connect(self.emitPrintSignal)
    self.previewButton.clicked.connect(self.emitPreviewSignal)
  # 发射预览信号
  def emitPreviewSignal( self ):
    if self.previewStatus.isChecked() == True:
      self.previewSignal[ int, str ].emit(1080, " Full Screen")
    elif self.previewStatus.isChecked() == False:
      self.previewSignal[ str ].emit("Preview")
  # 发射打印信号
  def emitPrintSignal( self ):
    pList = [ ]
    pList.append(self.numberSpinBox.value())
    pList.append(self.styleCombo.currentText())
    self.printSignal.emit(pList)
  def printPaper( self, list ):
    self.resultLabel.setText("打印: " + "份数:" + str(list[ 0 ]) + " 纸张:" + str(list[ 1 ]))
  def previewPaperWithArgs( self, style, text ):
    self.resultLabel.setText(str(style) + text)
  def previewPaper( self, text ):
    self.resultLabel.setText(text)
    # 重载点击键盘事件
  def keyPressEvent( self, event ):
    if event.key() == Qt.Key_F1:
      self.helpSignal.emit("help message")
  # 显示帮助消息
  def showHelpMessage( self, message ):
    self.resultLabel.setText(message)
    self.statusBar().showMessage(message)
if __name__ == "__main__":
  app = QApplication(sys.argv)
  win = MyMainWindow()
  win.show()
  sys.exit(app.exec_())

运行程序,显示效果如图

python GUI库图形界面开发之PyQt5结合Qt Designer创建信号与槽的详细方法与实例

代码分析

在上面的例子中,通过PyQtSignal()定义了三个信号,一个str参数类型的信号,一个list类型参数类型的信号,一个多重载版本的信号,包括一个int和str类型参数的信号,以及带str类型参数的信号

    helpSignal = pyqtSignal(str)

    printSignal = pyqtSignal(list)

    # 声明一个多重载版本的信号,包括了一个带int和str类型参数的信号,以及带str参数的信号

    previewSignal = pyqtSignal([ int, str ], [ str ])

对于绑定信号与槽,这里着重说明多重版本的信号绑定,prieviewSignal有两个版本,即previewSignal(str)和prievewSignal(int ,str),由于两个版本,因此在绑定的时候,需要显示指定信号与槽的绑定

        self.helpSignal.connect(self.showHelpMessage)

        self.printSignal.connect(self.printPaper)

        self.previewSignal[ str ].connect(self.previewPaper)

        self.previewSignal[ int, str ].connect(self.previewPaperWithArgs)

在Qt的机制中,根据所传递信号的参数类型和个数,连接到不同的槽函数

    def emitPreviewSignal( self ):

        if self.previewStatus.isChecked() == True:

            self.previewSignal[ int, str ].emit(1080, " Full Screen")

        elif self.previewStatus.isChecked() == False:

            self.previewSignal[ str ].emit("Preview")

信号发射可以传递python数据类型的参数,本例中的printSignal信号可以传递list类型的参数plist

 def emitPrintSignal( self ):

        pList = [ ]

        pList.append(self.numberSpinBox.value())

        pList.append(self.styleCombo.currentText())

        self.printSignal.emit(pList)

通过复写KeyPressEvent()方法,对F1键进行功能扩展,这里通过复写keyPressEvent()方法模拟发射所需的信号,来完成对应的任务

  def keyPressEvent( self, event ):

        if event.key() == Qt.Key_F1:

          self.helpSignal.emit("help message")

本文主要讲解了PyQt5结合Qt Designer创建信号与槽的详细方法与实例,另外一篇关于PyQt5结合Qt Designer创建信号与槽的文章 python GUI库图形界面开发之PyQt5信号与槽基本操作 大家也可以结合阅读下,更多关于 PyQt5信号与槽的知识请查看下面的相关链接

Python 相关文章推荐
python进阶教程之函数对象(函数也是对象)
Aug 30 Python
为python设置socket代理的方法
Jan 14 Python
使用Python操作Elasticsearch数据索引的教程
Apr 08 Python
Python常用的爬虫技巧总结
Mar 28 Python
python3 实现的人人影视网站自动签到
Jun 19 Python
Python matplotlib的使用并自定义colormap的方法
Dec 13 Python
PyCharm 2019.3发布增加了新功能一览
Dec 08 Python
python 将dicom图片转换成jpg图片的实例
Jan 13 Python
浅谈sklearn中predict与predict_proba区别
Jun 28 Python
Python3爬虫中关于Ajax分析方法的总结
Jul 10 Python
Python timeit模块原理及使用方法
Oct 10 Python
python实现计算器简易版
Dec 17 Python
python输出第n个默尼森数的实现示例
Mar 08 #Python
Tensorflow之梯度裁剪的实现示例
Mar 08 #Python
Django自定义全局403、404、500错误页面的示例代码
Mar 08 #Python
Django 自定义404 500等错误页面的实现
Mar 08 #Python
Python loguru日志库之高效输出控制台日志和日志记录
Mar 07 #Python
Centos7下源码安装Python3 及shell 脚本自动安装Python3的教程
Mar 07 #Python
Django接收照片储存文件的实例代码
Mar 07 #Python
You might like
PHP中HTTP方式下的Gzip压缩传输方法举偶
2007/02/15 PHP
php下使用iconv需要注意的问题
2010/11/20 PHP
PHP中spl_autoload_register函数的用法总结
2013/11/07 PHP
php与flash as3 socket通信传送文件实现代码
2014/08/16 PHP
PHP  实现等比压缩图片尺寸和大小实例代码
2016/10/08 PHP
PHP使用curl函数发送Post请求的注意事项
2016/11/26 PHP
JavaScript的eval JSON object问题
2009/11/15 Javascript
xml转json的js代码
2012/08/28 Javascript
jquery自定义属性(类型/属性值)
2013/05/21 Javascript
jQuery子窗体取得父窗体元素的方法
2015/05/11 Javascript
jQuery事件绑定on()与弹窗实现代码
2016/04/28 Javascript
node.js 中间件express-session使用详解
2017/05/20 Javascript
vue实现app页面切换动画效果实例
2017/05/23 Javascript
JS中的两种数据类型及实现引用类型的深拷贝的方法
2018/08/12 Javascript
移动端图片上传旋转、压缩问题的方法
2018/10/16 Javascript
详解Howler.js Web音频播放终极解决方案
2020/08/23 Javascript
使用Python中PDB模块中的命令来调试Python代码的教程
2015/03/30 Python
基于Pandas读取csv文件Error的总结
2018/06/15 Python
Python交互环境下实现输入代码
2018/06/22 Python
Python通过zookeeper实现分布式服务代码解析
2020/07/22 Python
python安装sklearn模块的方法详解
2020/11/28 Python
CSS教程:CSS3圆角属性
2009/04/02 HTML / CSS
Airbnb爱彼迎官网:成为爱彼迎房东,赚取收入
2019/03/14 全球购物
Servlet如何得到服务器的信息
2015/12/22 面试题
银行优秀员工事迹
2014/02/06 职场文书
《尊严》教学反思
2014/02/11 职场文书
秋季运动会广播稿大全
2014/02/17 职场文书
好学生评语大全
2014/05/05 职场文书
文明城市创建标语
2014/06/16 职场文书
承诺书样本
2014/08/30 职场文书
基层党员学习党的群众路线教育实践活动心得体会
2014/11/04 职场文书
2015年实习单位评语
2015/03/25 职场文书
2015年学校党支部工作总结
2015/04/01 职场文书
乔布斯辞职信(中英文对照)
2015/05/12 职场文书
银行柜员优质服务心得体会
2016/01/22 职场文书
Python实现拼音转换
2021/06/07 Python