热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PyQt5(五)信号与槽机制

信号和槽机制是QT的核心机制,要精通QT编程就必须对信号和槽有所了解。信号和槽是一种高级接口,应用于对象之间的通信,它是QT的核心特性&#

信号和槽机制是 QT 的核心机制,要精通 QT 编程就必须对信号和槽有所了解。信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重要地方。


信号和槽是用来在对象间传递数据的方法:当一个特定事件发生的时候,信号会被发射出来,槽调用是用来响应相应的信号的。Qt中对象已经包含了许多预定义的信号(基本组件都有各自特有的预定义的信号),根据使用的场景也可以添加新的信号。同样Qt的对象中已经包含了许多预定义的槽函数,但也可以根据使用的场景添加新的槽函数。


一、概念简介

所有继承qwidget的控件都支持信号与槽机制。

信号:当一个信号发生改变时,向外界发出的信息。

当一个信号被发射的时候,与其关联的槽函数被立刻执行。其中该对象只负责发送信号,发射该信号的对象并不知道是那个对象在接收这个信号。这样保证了对象与对象之间的低耦合。
如果存在信号和多个槽函数相关联的时候,当信号被发射时,这些槽的执行顺序将会是随机的、不确定的。

槽:一个执行某些操作的函数或者方法。

当和槽连接的信号被发射时,槽会被调用。一个槽并不知道是否有任何信号与自己相连接。

信号与槽机制:主要分两种

手动操作:信号连接槽

自动操作:当信号发出时,连续的槽函数会自动执行

信号连接

通过调用 QObject 对象的 connect 函数来将某个对象的信号与另外一个对象的槽函数相关联,这样当发射者发射信号时,接收者的槽函数将被调用。该函数的定义如下:

object.信号.connet(槽函数)

当信号与槽没有必要继续保持关联时,可以使用 disconnect 函数来断开连接。其定义如下:

disconnect(槽函数)

信号和槽的特点:

1.一个信号可以连接到多个槽:当信号发出后,槽函数都会被调用,但是调用的顺序是随机的,不确定的。

2.多个信号可以连接到同一个槽:其中任何一个信号发出,槽函数都会被执行。

3.信号的参数可以是任何的Python类型,如list,dict等python独有的类型。自定义信号的时候举例说明。

4.信号和槽的连接可以被移除:比如断开某个特定信号的关联。

5.信号可以和另外一个信号进行关联:第一个信号发出后,第二个信号也同时发送。比如关闭系统的信号发出之后,同时会发出保存数据的信号。


二、代码样例

整体代码如下:

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,QGridLayout,QLabel,QHBoxLayout, QGroupBox,QVBoxLayout, QApplication,QProgressBar,QPushButton,QMessageBox)class SignalSlot(QWidget):def __init__(self):super(SignalSlot,self).__init__() self.initUI()def initUI(self):self.controlsGroup = QGroupBox("运行样本")self.lcdNumber = QLCDNumber(self)self.slider = QSlider(Qt.Horizontal, self)self.pBar = QProgressBar(self)vbox = QVBoxLayout()vbox.addWidget(self.pBar)vbox.addWidget(self.lcdNumber)vbox.addWidget(self.slider)self.controlsGroup.setLayout(vbox)controlsLayout = QGridLayout()self.label1 = QLabel("保存状态:")self.saveLabel = QLabel()self.label2 = QLabel("运行状态:")self.runLabel = QLabel()self.buttonSave = QPushButton("保存")self.buttonRun = QPushButton("运行")self.buttonStop = QPushButton("停止")self.buttonDisconnect = QPushButton("解除关联")self.buttonConnect = QPushButton("绑定关联")controlsLayout.addWidget(self.label1,0,0)controlsLayout.addWidget(self.saveLabel,0,1)controlsLayout.addWidget(self.label2,1,0)controlsLayout.addWidget(self.runLabel,1,1)controlsLayout.addWidget(self.buttonSave,2,0)controlsLayout.addWidget(self.buttonRun,2,1)controlsLayout.addWidget(self.buttonStop,2,2)controlsLayout.addWidget(self.buttonDisconnect,3,0)controlsLayout.addWidget(self.buttonConnect,3,1)layout = QHBoxLayout()layout.addWidget(self.controlsGroup)layout.addLayout(controlsLayout)self.setLayout(layout)self.buttonRun.clicked.connect(self.buttonSave.clicked)self.slider.valueChanged.connect(self.pBar.setValue)self.slider.valueChanged.connect(self.lcdNumber.display)self.buttonSave.clicked.connect(self.showMessage)self.buttonRun.clicked.connect(self.showMessage)self.buttonDisconnect.clicked.connect(self.unbindConnection)self.buttonConnect.clicked.connect(self.bindConnection)self.buttonStop.clicked.connect(self.stop)self.setGeometry(300, 500, 500, 180)self.setWindowTitle('信号和槽')def showMessage(self):if self.sender().text() == "保存":self.saveLabel.setText("Saved")elif self.sender().text() == "运行":self.saveLabel.setText("Saved")self.runLabel.setText("Running")def unbindConnection(self):self.slider.valueChanged.disconnect()def bindConnection(self):self.slider.valueChanged.connect(self.pBar.setValue)self.slider.valueChanged.connect(self.lcdNumber.display)def stop(self):self.saveLabel.setText("")self.runLabel.setText("")if __name__ == '__main__':app = QApplication(sys.argv)ex = SignalSlot()ex.show()sys.exit(app.exec_())

控件说明:


控件类型控件名称作用
controlsGroupQGroupBox为构建分组框提供了支持。分组框通常带有一个边框和一个标题栏,作为容器部件来使用,在其中可以布置各种窗口部件。
lcdNumberQLCDNumber用于显示一个带有类似液晶显示屏效果的数字。
sliderQSlider提供一个垂直或者水平的滑动条,滑动条是一个用于控制有界值典型的控件,它允许用户沿水平或者垂直方向在某一范围内移动滑块,并将滑块所在的位置转换为一个合法范围内的整数值
pBarQProgressBar提供了一个水平或垂直的进度条
label1QLabel
  • 占位符
  • 显示文本
  • 显示图片
  • 放置gif动画
  • 超链接
  • 提示标记
buttonSaveQPushButton常用的按钮控件

界面说明: 

程序样本运行的界面逻辑,先设定运行的程序样本数量,然后先保存后运行的逻辑状态。通过slider的滑动来改变progressBar和LCD的显示数据;“保存”按钮保存运行的样本;“运行”按钮运行程序样本;“解除关联”解除slider.valueChanged信号的绑定,此时slider的滑动,不会改变progressBar和LCD的显示。

self.controlsGroup = QGroupBox("运行样本")
self.lcdNumber = QLCDNumber(self)
self.slider = QSlider(Qt.Horizontal, self)
self.pBar = QProgressBar(self)
vbox = QVBoxLayout()
vbox.addWidget(self.pBar)
vbox.addWidget(self.lcdNumber)
vbox.addWidget(self.slider)
self.controlsGroup.setLayout(vbox)

实例化一个QGroupBox,在其中添加QProgressBar、QLCDNumber、QSlider控件。

controlsLayout = QGridLayout()
self.label1 = QLabel("保存状态:")
self.saveLabel = QLabel()
self.label2 = QLabel("运行状态:")
self.runLabel = QLabel()
self.buttonSave = QPushButton("保存")
self.buttonRun = QPushButton("运行")
self.buttonStop = QPushButton("停止")
self.buttonDisconnect = QPushButton("解除关联")
self.buttonConnect = QPushButton("绑定关联")controlsLayout.addWidget(self.label1,0,0)
controlsLayout.addWidget(self.saveLabel,0,1)
controlsLayout.addWidget(self.label2,1,0)
controlsLayout.addWidget(self.runLabel,1,1)
controlsLayout.addWidget(self.buttonSave,2,0)
controlsLayout.addWidget(self.buttonRun,2,1)
controlsLayout.addWidget(self.buttonStop,2,2)
controlsLayout.addWidget(self.buttonDisconnect,3,0)
controlsLayout.addWidget(self.buttonConnect,3,1)

通过QGridLayout()添加标签以及按钮。

layout = QHBoxLayout()
layout.addWidget(self.controlsGroup)
layout.addLayout(controlsLayout)
self.setLayout(layout)

 最后通过QHBoxLayout将左右两个界面合并,形成最终界面。

信号与槽说明:

signal和slot进行绑定。
1.一个信号绑定多个槽:

self.slider.valueChanged.connect(self.pBar.setValue)self.slider.valueChanged.connect(self.lcdNumber.display)

slider控件的valueChanged信号,同时与QProgressBar的setValue(),QLCDNumber的display()槽函数绑定,当valueChanged信号触发的时候,这两个槽函数均会被调用。

2.多个信号绑定到一个槽:

self.buttonSave.clicked.connect(self.showMessage)
self.buttonRun.clicked.connect(self.showMessage)

buttonSave和buttonRun这两个对象的clicked信号,同时绑定到showMessage()这个槽函数。无论哪一个信号被触发,showMessage()这个槽函数均会被调用,而根据self.sender().text() 这个函数来判断显示的不同内容。

3.信号和槽的连接可以被移除:

self.buttonDisconnect.clicked.connect(self.unbindConnection)

当buttonDisconnect信号触发之后,与其关联的槽函数unbindConnection()中就会执行disconnect()方法,如下:

def unbindConnection(self):self.slider.valueChanged.disconnect()

其中执行disconnect()的时候可以指定解除与某个特定的slot槽的关联,比如self.slider.valueChanged.disconnect(self.pBar.setValue),此时解除和QProgressBar的setValue()的关联,如果不指定,将解除和这个信号所有关联的槽。

4、信号与信号的关联:

self.buttonRun.clicked.connect(self.buttonSave.clicked)

在样例说明中提到,在运行之前要对样本进行保存,所以为了保证运行的时候执行了保存的操作,所以将buttonRun.clicked信号和buttonSave.clicked信号关联起来。

示例中在没有执行“保存”(buttonSave)的时候,执行“运行”(buttonRun),此时由于两个对象的clicked信号已经关联,所以buttonSave的clicked同样会执行。

最终结果:

本文是《从零开始学PyQt5》第五篇,希望小伙伴们可以多多支持,一起学习!



参考:

Pyqt5系列(七)-信号与槽机制_追逐阳光的风-CSDN博客_pyqt5信号和槽


推荐阅读
  • OpenMap教程4 – 图层概述
    本文介绍了OpenMap教程4中关于地图图层的内容,包括将ShapeLayer添加到MapBean中的方法,OpenMap支持的图层类型以及使用BufferedLayer创建图像的MapBean。此外,还介绍了Layer背景标志的作用和OMGraphicHandlerLayer的基础层类。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 展开全部下面的代码是创建一个立方体Thisexamplescreatesanddisplaysasimplebox.#Thefirstlineloadstheinit_disp ... [详细]
  • 标题: ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • 集合的遍历方式及其局限性
    本文介绍了Java中集合的遍历方式,重点介绍了for-each语句的用法和优势。同时指出了for-each语句无法引用数组或集合的索引的局限性。通过示例代码展示了for-each语句的使用方法,并提供了改写为for语句版本的方法。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • [echarts] 同指标对比柱状图相关的知识介绍及应用示例
    本文由编程笔记小编为大家整理,主要介绍了echarts同指标对比柱状图相关的知识,包括对比课程通过率最高的8个课程和最低的8个课程以及全校的平均通过率。文章提供了一个应用示例,展示了如何使用echarts制作同指标对比柱状图,并对代码进行了详细解释和说明。该示例可以帮助读者更好地理解和应用echarts。 ... [详细]
  • importjava.util.ArrayList;publicclassPageIndex{privateintpageSize;每页要显示的行privateintpageNum ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • python中安装并使用redis相关的知识
    本文介绍了在python中安装并使用redis的相关知识,包括redis的数据缓存系统和支持的数据类型,以及在pycharm中安装redis模块和常用的字符串操作。 ... [详细]
author-avatar
小三coolboy958_818
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有