zoukankan      html  css  js  c++  java
  • [PyQt]如何使用信号槽? codeio 博客园

    [PyQt]如何使用信号槽? - codeio - 博客园

    [PyQt]如何使用信号槽?

    前言

    信号(singal)与槽(slot)用于对象相互通信,信号:当某个对象的某个事件发生时,触发一个信号,槽:响应指定信号的所做的反应,其实信号槽类似于.NET里面的委托、事件,比如Repeater控件类,当行数据绑定后,触发一个ItemDataBound事件,不管使用者使用会监听该事件并做额外处理,其控件类内部都会触发该事件,这种机制很多程度提高了类的封装性和完整性。

    PyQt的窗体控件类已经有很多的内置信号,开发者也可以添加自己的自定义信号,信号槽有如下特点:

    - 一个信号可以连接到许多插槽
    - 一个信号也可以连接到另一个信号
    - 信号参数可以是任何Python类型
    - 一个插槽可以连接到许多信号
    - 连接可能会直接(同步)或排队(即异步
    - 连接可能会跨线程
    - 信号可能会断开

    (以上几条特点翻译于官方文档),接下来,我将以若干个实例,来体现以上几个特点。

    内置信号槽、自定义信号槽的使用

    内置信号槽的使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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_()

    运行结果:

    自定义信号槽的使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    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连接、断开连接以及多线程信号槽通信

    信号槽N对N连接、断开连接

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    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

    多线程信号槽通信

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    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的子类中声明

  • 相关阅读:
    docker指令汇总
    springboot(八) 嵌入式Servlet容器自动配置原理和容器启动原理
    RabbitMQ 消息确认机制
    RabbitMQ 最常用的三大模式
    RabbitMQ 核心概念
    RabbitMQ 之简单队列
    Spring 详解(三)------- SpringMVC拦截器使用
    slf4j 搭配 log4j2 处理日志
    Spring 详解(二)------- AOP关键概念以及两种实现方式
    Spring 详解(一)------- AOP前序
  • 原文地址:https://www.cnblogs.com/lexus/p/2819615.html
Copyright © 2011-2022 走看看