PySide中的信號和槽
本文主要介紹在PySide中如何使用信號和槽。傳統的使用方式已經在參考文檔里給出,我們的重點是解釋如何使用新的代碼風格來操作信號、槽。
PyQt中使用信號、槽的新代碼風格是在PyQt v4.5中介紹的,這個風格的主要目的是為Python程序員們提供一個符合Python風格的方式。
傳統方式:SINGAL和SLOT
QtCore.SIGNAL和QtCore.SLOT是Python使用Qt信號、槽傳送機制的接口。這就是我們所說的舊方式。
下面這個例子使用了QPushButton的點擊信號,而連接方法并非符合python習慣的語法。它需要通知對象,并將它的信號和另外個槽連接。
def someFunc():
print "someFunc has been called!"
...
button = QtGui.QPushButton("Call someFunc")
QtCore.QObject.connect(button, QtCore.SIGNAL('clicked()'), someFunc)
...
新風格:Signal()和Slot()
新風格使用了不同的語法創建并連接信號、槽。前面的例子可以重寫如下:
def someFunc():
print "someFunc has been called!"
button = QtGui.QPushButton("Call someFunc")
button.clicked.connect(someFunc)
...
使用QtCore.Singal()
信號可以使用QtCore.Signal()定義。Python類型和C類型都可以作為參數傳遞給它。假如你需要重載它,只需要用無組或列表地方式傳遞類型。
另外,它也可以接受命名參數(named argument) name來定義信號的名稱。如果沒有傳遞name,那么信號將會使用賦值變量的名稱。
第二個例子中使用了一組方式來顯示如何使用QtCore.Signal()
注意:信號只能在QObject的子類內定義,這種方式下信號的信息將會加入 QMetaObject結構中。
使用 QtCore.Slot()
槽可以用QtCore.Slot()賦值或者重載。同樣,想定義一個簽名僅僅需要傳遞給QtCore.Singal()一些類型。與Signal()類不同的是,想重載一個函數,你并不需要傳遞任何的無級或者列表,你需要做的是為每個不同的簽名定義一個不同的裝飾。如果沒看懂沒有關系,下面的例子將會讓你明了。
另外一個區別是關鍵字。Slot()接受一個name和一個result. result關鍵字定義的是返回值,可以是C或者Python的類型。name則與Signal中的一樣。如果沒有傳遞name,則使用函數的名字。
一組例子:
下面有一組例子,用來顯示如何在PySide中定義及連接信號、槽。有一些例子比較簡單,有一些則比較復雜。
1. Hello World: 基本的例子,顯示不使用任何參數的情況下連接信號和槽

import sys
from PySide 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_())
2. 接著,我們加了一些參數。是從 Hello World版本修改的。槽中添加了一些參數,同時創建了一個新的信號

import sys
from PySide import QtCore
# define a new slot that receives a string and has
# 'saySomeWords' as its name
@QtCore.Slot(str)
def saySomeWords(words):
print words
class Communicate(QtCore.QObject):
# create a new signal on the fly and name it 'speak'
speak = QtCore.Signal(str)
someone = Communicate()
# connect signal and slot
someone.speak.connect(saySomeWords)
# emit 'speak' signal
someone.speak.emit("Hello everybody!")
3. 添加一些重載。簡單地修改了前一個例子。下面是重載修飾符

import sys
from PySide import QtCore
# define a new slot that receives a C 'int' or a 'str'
# and has 'saySomething' as its name
@QtCore.Slot(int)
@QtCore.Slot(str)
def saySomething(stuff):
print stuff
class Communicate(QtCore.QObject):
# create two new signals on the fly: one will handle
# int type, the other will handle strings
speakNumber = QtCore.Signal(int)
speakWord = QtCore.Signal(str)
someone = Communicate()
# connect signal and slot properly
someone.speakNumber.connect(saySomething)
someone.speakWord.connect(saySomething)
# emit each 'speak' signal
someone.speakNumber.emit(10)
someone.speakWord.emit("Hello everybody!")
4. 最后一個例子,使用了槽重載以及一些復雜的信號連接及發射。

import sys
from PySide import QtCore
# define a new slot that receives an C 'int' or a 'str'
# and has 'saySomething' as its name
@QtCore.Slot(int)
@QtCore.Slot(str)
def saySomething(stuff):
print stuff
class Communicate(QtCore.QObject):
# create two new signals on the fly: one will handle
# int type, the other will handle strings
speak = QtCore.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(saySomething)
someone.speak[str].connect(saySomething)
# 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!")
PyQt兼容模式:
PyQt使用了另外一種方式。為了將PyQt腳本轉而使用PySide運行,只需要使用下面的代碼進行修改。
from PySide.QtCore import Slot as pyqtSlot
或者
QtCore.pyqtSlot = QtCore.Slot