目录
本文介绍了Qt for Python中信号和插槽的使用。重点说明新式信号和槽的使用,传统语法也作为参考。
原文链接: https://wiki.qt.io/Qt_for_Python_Signals_and_Slots
传统语法: SIGNAL () 和 SLOT()
使用QtCore.SIGNAL()和QtCore.SLOT()宏。
下面的示例使用来自QPushButton的单击信号。 connect方法具有非python友好语法。必须通知对象,其信号(通过宏)和要连接的槽函数。
import sys
from PySide2.QtWidgets import QApplication, QPushButton
from PySide2.QtCore import SIGNAL, QObject
def func():
print("func has been called!")
app = QApplication(sys.argv)
button = QPushButton("Call func")
QObject.connect(button, SIGNAL ('clicked()'), func)
button.show()
sys.exit(app.exec_())
新语法: Signal() and Slot()
使用不同的语法来创建和连接信号和槽。前面的示例可以重写为:
import sys
from PySide2.QtWidgets import QApplication, QPushButton
def func():
print("func has been called!")
app = QApplication(sys.argv)
button = QPushButton("Call func")
button.clicked.connect(func)
button.show()
sys.exit(app.exec_())
使用 QtCore.Signal()
可以使用QtCore.Signal()定义信号。可以将Python类型和C类型作为参数传递给它。如果需要重载,只需将类型作为元组或列表传递。
之外,它还可以接受定义信号名称的参数。如果没有传递任何名称作为参数,则新信号将与为其分配的变量具有相同的名称。
下面的示例提供了有关QtCore.Signal()使用方法。
注意:只能在QObject继承的类中定义信号。这样,信号信息将添加到类QMetaObject结构中。
使用QtCore.Slot()
使用装饰器QtCore.Slot()分配和重载槽函数。同样,要定义签名,只需传递类似QtCore.Signal()的参数类型。与Signal()类不同,要重载函数,您不必将每个变量都作为元组或列表传递。而是必须为每个不同的签名定义一个新的装饰器。
另一个区别是关键字。 Slot()接受名称和结果。 result关键字定义了将返回的类型,可以是C或Python类型。名称的行为与Signal()中的行为相同。如果没有传递任何名称作为名称,则新槽函数将与正在装饰的函数具有相同的名称。
示例
以下示例说明了如何在PySide2中定义和连接信号和槽。给出了基本连接和复杂的连接。
基本示例
如何将信号连接到没有任何参数的插槽。
import sys
from PySide2 import QtCore, QtGui
# define a function that will be used as a slot
def sayHello():
print 'Hello world!'
app = QtGui.QApplication(sys.argv)
button = QtGui.QPushButton('Say hello!')
# connect the clicked signal to the sayHello slot
button.clicked.connect(sayHello)
button.show()
sys.exit(app.exec_())
添加参数
这是经过修改的Hello World版本。一些参数被添加到槽中并创建一个新信号。
import sys
from PySide2.QtWidgets import QApplication, QPushButton
from PySide2.QtCore import QObject, Signal, Slot
app = QApplication(sys.argv)
# define a new slot that receives a string and has
# 'saySomeWords' as its name
@Slot(str)
def say_some_words(words):
print(words)
class Communicate(QObject):
# create a new signal on the fly and name it 'speak'
speak = Signal(str)
someone = Communicate()
# connect signal and slot
someone.speak.connect(say_some_words)
# emit 'speak' signal
someone.speak.emit("Hello everybody!")
添加重载
对前面的示例进行了小的修改,现在带有重载的装饰器。
import sys
from PySide2.QtWidgets import QApplication, QPushButton
from PySide2.QtCore import QObject, Signal, Slot
app = QApplication(sys.argv)
# define a new slot that receives a C 'int' or a 'str'
# and has 'saySomething' as its name
@Slot(int)
@Slot(str)
def say_something(stuff):
print(stuff)
class Communicate(QObject):
# create two new signals on the fly: one will handle
# int type, the other will handle strings
speak_number = Signal(int)
speak_word = Signal(str)
someone = Communicate()
# connect signal and slot properly
someone.speak_number.connect(say_something)
someone.speak_word.connect(say_something)
# emit each 'speak' signal
someone.speak_number.emit(10)
someone.speak_word.emit("Hello everybody!")
槽函数重载和更复杂的信号连接和发射的示例
注意,将参数传递给信号时,请使用 [ ]:
import sys
from PySide2.QtWidgets import QApplication, QPushButton
from PySide2.QtCore import QObject, Signal, Slot
app = QApplication(sys.argv)
# define a new slot that receives a C 'int' or a 'str'
# and has 'saySomething' as its name
@Slot(int)
@Slot(str)
def say_something(stuff):
print(stuff)
class Communicate(QObject):
# create two new signals on the fly: one will handle
# int type, the other will handle strings
speak = Signal((int,), (str,))
someone = Communicate()
# connect signal and slot. As 'int' is the default
# we have to specify the str when connecting the
# second signal
someone.speak.connect(say_something)
someone.speak[str].connect(say_something)
# emit 'speak' signal with different arguments.
# we have to specify the str as int is the default
someone.speak.emit(10)
someone.speak[str].emit("Hello everybody!")
发出信号的对象方法示例
import sys
from PySide2.QtCore import QObject, Signal
# Must inherit QObject for signals
class Communicate(QObject):
speak = Signal()
def __init__(self):
super(Communicate, self).__init__()
self.speak.connect(self.say_hello)
def speaking_method(self):
self.speak.emit()
def say_hello(self):
print("Hello")
someone = Communicate()
someone.speaking_method()
从另一个线程发出信号的示例:
import sys
from PySide2.QtCore import QObject, Slot, Signal, QThread
# Create the Slots that will receive signals
@Slot(str)
def update_a_str_field(message):
print(message)
@Slot(int)
def update_a_int_field(self, value):
print(value)
# Signals must inherit QObject
class Communicate(QObject):
signal_str = Signal(str)
signal_int = Signal(int)
class WorkerThread(QThread):
def __init__(self, parent=None):
QThread.__init__(self, parent)
self.signals = Communicate()
# Connect the signals to the main thread slots
self.signals.signal_str.connect(parent.update_a_str_field)
self.signals.signal_int.connect(parent.update_a_int_field)
def run(self):
self.signals.update_a_int_field.emit(1)
self.signals.update_a_str_field.emit("Hello World.")
信号是实例拥有的运行时对象,不是类属性
# Erroneous: refers to class Communicate, not an instance of the class
Communicate.speak.connect(say_something)
# raises exception: AttributeError: 'PySide2.QtCore.Signal' object has no attribute 'connect'