转载:pyqt线程间通过 信号/槽 通信

摘要:
  PyQt的窗体控件类已经有很多的内置信号,开发者也可以添加自己的自定义信号,信号槽有如下特点:    -一个信号可以连接到许多插槽。    -信号参数可以是任何Python类型。    -连接可能会直接(即同步)或排队(即异步)。    -连接可能会跨线程。    -信号可能会断开  ,接下来,我将以若干个实例,来体现以上几个特点。

转自:http://blog.sina.com.cn/s/blog_613d5bb701016qzv.html

信号(singal)与槽(slot)用于对象相互通信,信号:当某个对象的某个事件发生时,触发一个信号,槽:响应指定信号的所做的反应,其实信号槽类似于.NET里面的委托、事件,比如Repeater控件类,当行数据绑定后,触发一个ItemDataBound事件,不管使用者使用会监听该事件并做额外处理,其控件类内部都会触发该事件,这种机制很多程度提高了类的封装性和完整性。
  PyQt的窗体控件类已经有很多的内置信号,开发者也可以添加自己的自定义信号,信号槽有如下特点:
    - 一个信号可以连接到许多插槽。
    - 一个信号也可以连接到另一个信号。
    - 信号参数可以是任何Python类型。
    - 一个插槽可以连接到许多信号。
    - 连接可能会直接(即同步)或排队(即异步)。
    - 连接可能会跨线程。
    - 信号可能会断开
  (以上几条特点翻译于官方文档),接下来,我将以若干个实例,来体现以上几个特点。
内置信号槽的使用
from PyQt4.QtGui import *
from PyQt4.QtCore import *
def sinTest():
    btn.setText("按钮文本改变")
app = QApplication([])
main = QWidget()
main.resize(200,100)
btn = QPushButton("按钮文本",main)
##按钮btn的内置信号连接名为sinTest的槽
btn.clicked.connect(sinTest)
main.show()  
app.exec_()
from PyQt4.QtGui import *
from PyQt4.QtCore import *
def sinTest():
    btn.setText("按钮文本改变")
app = QApplication([])
main = QWidget()
main.resize(200,100)
btn = QPushButton("按钮文本",main)
##按钮btn的内置信号连接名为sinTest的槽
btn.clicked.connect(sinTest)
main.show()  
app.exec_()
from PyQt4.QtGui import *
from PyQt4.QtCore import *
def sinTest():
    btn.setText("按钮文本改变")
app = QApplication([])
main = QWidget()
main.resize(200,100)
btn = QPushButton("按钮文本",main)
##按钮btn的内置信号连接名为sinTest的槽
btn.clicked.connect(sinTest)
main.show()
app.exec_()
运行结果:
自定义信号槽的使用
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class SinClass(QObject):
    ##声明一个无参数的信号
    sin1 = pyqtSignal()
    ##声明带一个int类型参数的信号
    sin2 = pyqtSignal(int)
    ##声明带一个int和str类型参数的信号
    sin3 = pyqtSignal(int,str)
    ##声明带一个列表类型参数的信号
    sin4 = pyqtSignal(list)
    ##声明带一个字典类型参数的信号
    sin5 = pyqtSignal(dict)
    ##声明一个多重载版本的信号,包括了一个带int和str类型参数的信号,以及带str参数的信号
    sin6 = pyqtSignal([int,str], [str])
    def __init__(self,parent=None):
        super(SinClass,self).__init__(parent)
        ##信号连接到指定槽
        self.sin1.connect(self.sin1Call)
        self.sin2.connect(self.sin2Call)
        self.sin3.connect(self.sin3Call)
        self.sin4.connect(self.sin4Call)
        self.sin5.connect(self.sin5Call)
        self.sin6[int,str].connect(self.sin6Call)
        self.sin6[str].connect(self.sin6OverLoad)
        ##信号发射
        self.sin1.emit()
        self.sin2.emit(1)
        self.sin3.emit(1,"text")
        self.sin4.emit([1,2,3,4])
        self.sin5.emit({"name":"codeio","age":"25"})
        self.sin6[int,str].emit(1,"text")
        self.sin6[str].emit("text")
    def sin1Call(self):
        print("sin1 emit")
    def sin2Call(self,val):
        print("sin2 emit,value:",val)
    def sin3Call(self,val,text):
        print("sin3 emit,value:",val,text)
    def sin4Call(self,val):
        print("sin4 emit,value:",val)
    def sin5Call(self,val):
        print("sin5 emit,value:",val)
    def sin6Call(self,val,text):
        print("sin6 emit,value:",val,text)
    def sin6OverLoad(self,val):
        print("sin6 overload emit,value:",val)
sin = SinClass()
运行结果:
sin1 emit
sin2 emit,value: 1
sin3 emit,value: 1 text
sin4 emit,value: [1, 2, 3, 4]
sin5 emit,value: {'age': '25', 'name': 'codeio'}
sin6 emit,value: 1 text
sin6 overload emit,value: text
信号槽N对N连接、断开连接
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class SinClass(QObject):
    ##声明一个无参数的信号
    sin1 = pyqtSignal()
    ##声明带一个int类型参数的信号
    sin2 = pyqtSignal(int)
    def __init__(self,parent=None):
        super(SinClass,self).__init__(parent)
        ##信号sin1连接到sin1Call和sin2Call这两个槽
        self.sin1.connect(self.sin1Call)
        self.sin1.connect(self.sin2Call)
        ##信号sin2连接到信号sin1
        self.sin2.connect(self.sin1)
        ##信号发射
        self.sin1.emit()
        self.sin2.emit(1)
        ##断开sin1、sin2信号与各槽的连接
        self.sin1.disconnect(self.sin1Call)
        self.sin1.disconnect(self.sin2Call)
        self.sin2.disconnect(self.sin1)
        ##信号sin1和sin2连接同一个槽sin1Call
        self.sin1.connect(self.sin1Call)
        self.sin2.connect(self.sin1Call)
        ##信号再次发射
        self.sin1.emit()
        self.sin2.emit(1)
    def sin1Call(self):
        print("sin1 emit")
    def sin2Call(self):
        print("sin2 emit")
sin = SinClass()
运行结果:
sin1 emit
sin2 emit
sin1 emit
sin2 emit
sin1 emit
sin1 emit
多线程信号槽通信
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Main(QWidget):
    def __init__(self, parent = None):
        super(Main,self).__init__(parent)
        ##创建一个线程实例并设置名称、变量、信号槽
        self.thread = MyThread()
        self.thread.setIdentity("thread1")
        self.thread.sinOut.connect(self.outText)
        self.thread.setVal(6)
    def outText(self,text):
        print(text)
class MyThread(QThread):
    sinOut = pyqtSignal(str)
    def __init__(self,parent=None):
        super(MyThread,self).__init__(parent)
        self.identity = None
    def setIdentity(self,text):
        self.identity = text
    def setVal(self,val):
        self.times = int(val)
        ##执行线程的run方法
        self.start()
    def run(self):
        while self.times > 0 and self.identity:
            ##发射信号
            self.sinOut.emit(self.identity+" "+str(self.times))
            self.times -= 1
app = QApplication([])
main = Main()
main.show()
app.exec_()
运行结果:
thread1 6
thread1 5
thread1 4
thread1 3
thread1 2
thread1 1
  该篇主要介绍了信号槽多对多连接、连接断开、多线程如何使用信号槽进行通信,Qt除了窗体部件类,还提供了很多其他系统相关操作类,使用起来很方便,多线程使用了Qt自带的QThread类,这里只是做了个简单的测试,多线程还有许多要深入探究的,有几个心得:
    - 对于单一信号连接多个槽的情况,发射信号后,槽的执行顺序就是信号槽连接的顺序
    - GUI所在的线程是主线程,线程之间可以通过信号槽来通信,这个方法适用于重写PyQt部件类后对外开发接口
    - 我使用的环境是:PyQt4.8.4,Qt4.7.2,Python3.2,这个版本的PyQt将使用新的信号槽风格
    - 槽的参数个数可以小于等于信号的参数个数, 换句话说,信号并不关心谁使用了它,怎么使用它,槽可以选择性地使用信号的参数
    - 用pyqtSignal来声明一个新信号,它的参数可能是Python的类型对象或者C++的类型
    - 新的信号只能在QObject的子类中声明

个人注解:

QMetaObject::invokeMethod()是Qt中的方法,在PyQt中应该也可行,但是没在PyQt试验过,。。。。。囧

免责声明:文章转载自《转载:pyqt线程间通过 信号/槽 通信》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇iTween研究院之学习笔记Move移动篇CentOS 7 64位 安装 PostgreSQL 9.2整理下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

python爬虫入门01:教你在 Chrome 浏览器轻松抓包

通过 python爬虫入门:什么是爬虫,怎么玩爬虫? 我们知道了什么是爬虫 也知道了爬虫的具体流程 那么在我们要对某个网站进行爬取的时候 要对其数据进行分析 就要知道应该怎么请求 就要知道获取的数据是什么样的 所以我们要学会怎么抓咪咪! 哦,不对。 我们要学会怎么数据抓包 虽然小馒头也是包的一种 ok...anyway... 打开我们的 Chrome...

Python 调试

【简介调试工具】 pdb使用如下代码就相当于添加断点了:import pdb    pdb.set_trace()  #设置断点的地方,放置于程序中 ipdb相对于python,我们更趋向于ipython,有漂亮的颜色,和<tab>补全提示,以及bash混用; 相对于python内置的pdb,ipdb的优势也正在于此,其实就是对ipython的...

Python使用Redis

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。Redis支持存储的value类型包括字符串(String), 哈希(Hash), 列表(list), 集合(set) 和 有序集合(sorted set)。 Redis官方文档:https://redis.io Red...

Python——继承

Python的继承是多继承机制,一个子类可以同时有多个直接父类;继承可以得到父类定义的方法,子类就可以复用父类的方法。 一、继承的语法 子类:实现继承的类。 父类(基类、超类):被继承的类。 子类继承父类是在定义子类时,将多个父类放在子类之后的圆括号内,如果定义类时,未指定这个类的直接父类,则默认继承object类,所以object类是所有类的父类(直接父...

使用 -命令行-给-python-安装whl文件,

whl文件下载到哪个位置,命令行就切入到哪里; 我的在D盘目录下,所以命令行切进D盘(CD):方式如下: 列出《用户目录》下的目录(dir): 因为我安装了2个版本的python所以给python2.7版本的用的是pip2,给python3安装用pip3.使用单个版本的就直接用pip即可:pip install xxx.whl   安装成功会有提示...

python smtp 群发邮件

最近工作中遇到使用脚本处理问题并发送结果邮件,使用python的smtp模块很简单的完成了实现。今天遇到一个问题,根据脚本的测试结果需要群发邮件,但是发送邮件的py文件只有首个地址收到了邮件。仔细排查发现个有意思的地方: 发送邮件的py大致如下: 1 def sendmail(message,to_addrs) 2 ................