信号与槽的详解

以前也写过这方面的知识,但是因为都是参照着别人的文章来写的,就是很虚,很浮夸,今天下午我又好好看了一下这方面的知识,查阅了一些资料,现在来写写我自己的发现。


接下来分为四大小点。

一、

信号和槽的基本认识

当对象的内部状态发生改变,信号就被发射。信号发射之后,它所连接的槽会被立即执行,就像一个普通函数调用一样。大部分窗口部件都预置了一些信号和槽,不同的部件信号和槽也不同。比如QPushButton的信号就有clicked,而QSpinBox的信号是valueChanged(int)/valueChanged(double)。我们也可以自定义自己感兴趣的信号和槽,也能自己发射信号。

---------------------------------------

     信号和槽有什么作用呢?

---------------------------------------

信号和槽用于对象之间的通讯,当一个窗口部件发生了变化,利用信号-槽机制,我们就能在另一个窗口或者本窗口上做出相应的动作。比如按下Button按钮,我们就能弹出一个窗口或者输出某个东西。这些动作是我们想要在按下Button按钮后想得到的。

---------------------------------------

         信号和槽的基本规则

---------------------------------------

信号和槽可以使用任何数量、任何类型的参数。

一个信号的签名必须与它的接收槽的签名相匹配。(实际上一个槽的签名可以比它接收的信号的签名少,因为它可以忽略额外的签名。)注:签名可以简单理解为参数

一个信号可以和多个槽连接在一起,一个槽也可以由多个信号连接,信号也可以连接信号


二、

连接信号和槽的基本函数

一般我们会用connect函数对信号和槽进行连接。这里我就详细地讲一下如何用这个函数,以及相应的几种方式。

①bool QObject.connect (QObject, SIGNAL(), QObject, SLOT(), Qt.ConnectionType = Qt.AutoConnection)

1当这个连接成功时,返回True,否则返回False

The function returns true if it successfully connects the signal to the slot. It will return false if it cannot create the connection, for example, ifQObject is unable to verify the existence of eithersignal ormethod, or if their signatures aren't compatible.

当不能识别出该QObject是否带有该信号或槽时,则会connect失败。

2.参照该链接代码链接,self.connect(exit,QtCore.SIGNAL('triggered()'),QtCore.SLOT('close()'))   来自链接内第15行

该句就是应用上面的语法。这一种语法是针对槽被SLOT宏包裹的类型的

为什么链接里的第15行代码好像和语法有一点不一样呢?严格说来是要在QtCore.SLOT前面加上self的,由于前面的QObject是引用的self,故这里可以省略self,如果前面的QObject不是self的话,就必须加上self了。

该句也可以写成这样:QDialog.connect(exit,QtCore.SIGNAL('triggered()'),self,QtCore.SLOT('close()'))    注:QDialog也可以换成QWidget等一些其他QObject的子类


②bool QObject.connect (QObject, SIGNAL(), callable, Qt.ConnectionType = Qt.AutoConnection)

1.该句等同于connect(sender,signal,this,method,type).

2.callable相当于函数调用,该函数可以是本类里面的函数,也可以是一个类外的普通函数。


三、如何自定义信号和槽并发射

自定义信号可以利用PyQt4.QtCore.pyqtSignal函数。

1.定义无参数的信号

from PyQt4.QtGui import *
from PyQt4.QtCore import *
class MySignal(QtGui.QPushButton):
	clicked = pyqtSignal()

2.定义有参数的信号
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class MySignal(QPushButton):
	clicked = pyqtSignal(int)

3.发射自定义信号(先自定义信号)
import  sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class MySignal(QDialog):
    Myclicked = pyqtSignal()
    def __init__(self,parent=None):
        super(MySignal,self).__init__(parent)
        button = QPushButton("click me",self)
        self.connect(button, SIGNAL("clicked()"), self.Myclicked.emit)
        self.connect(self, SIGNAL("Myclicked()"),showMsg)
def showMsg():
    print 1
app = QApplication(sys.argv)
signal=MySignal()
signal.show()
app.exec_()
通过emit函数我们就可以把自定义的Myclicked信号发射出去,并将Myclicked信号与showMsg函数连接在一起。

4.另外一种发射自定义信号方式。(不用先自定义信号)

from PyQt4.QtGui import *
from PyQt4.QtCore import *
class MySignal(QPushButton):
	button=QPushButton("click me")
	self.connect(button ,SIGNAL("clicked()"),self.emitMyclicked)
	self.connect(self,SIGNAL("Myclicked()",showMsg)
 
	def emitMyclicked(self):
 		self.emit(SIGNAL("Myclicked()"))
	def showMsg():
 		print 1


5.发射带参数的自定义信号(不能效仿第三种方法是因为connect的时候槽函数不能带具体的参数名)
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class MySignal(QPushButton):
 	button=QPushButton("click me")
	Myclicked = pyqtSignal(int) #该句必须放在Init函数外
	self.id=2
	self.connect(button ,SIGNAL("clicked()"),self.emitMyclicked)
	self.connect(self,SIGNAL("Myclicked(int)",showMsg)
 
	def emitMyclicked(self):
		self.Myclicked.emit(self.id)
	def showMsg(a):
		print a
 
6.另外一种发射带参数的自定义信号方式(同样不用自定义信号)
class MySignal(QPushButton):


	button=QPushButton("click me")
	self.id=2
	self.connect(button ,SIGNAL("clicked()"),self.emitMyclicked)
	self.connect(self,SIGNAL("Myclicked(int)",showMsg)
	
	def emitMyclicked(self):
		self.emit(SIGNAL("Myclicked(int)"),self.id)
def showMsg(a):
	print a

7.自定义槽
利用@pyqtSlot()

#coding=utf-8
import  sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class MySignal(QDialog):

    def __init__(self,parent=None):
        super(MySignal,self).__init__(parent)
        self.id=2
        button = QPushButton("click me",self)
        self.connect(button, SIGNAL("clicked()"),SLOT("onclicked()"))

    @pyqtSlot()
    def onclicked(self):
        QMessageBox.information(self,u"提示","are you sure to quit??")
app = QApplication(sys.argv)
signal=MySignal()
signal.show()
app.exec_()


四、多个按钮连在一个槽上,当槽发生调用时如何识别出是哪个按钮的调用 在一个槽的内部,我们可以通过调用sender()发现到底调用信号是来自哪个QObject对象。 具体例子见链接
欢迎评论~




你可能感兴趣的:(#,PyQt(停更))