PyQt4 信号与槽
我正在用PyQt4写我的第一个Python应用程序。我有一个主窗口(MainWindow)和一个对话框类(Dialog),这个对话框是主窗口类的一部分:
self.loginDialog = LoginDialog();
我使用了槽(slots)和信号(signals)。这是在主窗口中建立的连接:
QtCore.QObject.connect(self.loginDialog, QtCore.SIGNAL("aa(str)"), self.login)
然后我尝试在对话框类中发出信号(我确定信号是发出的):
self.emit(QtCore.SIGNAL("aa"), "jacek")
可惜的是,槽没有被调用。我也尝试过不带参数的方式,以及不同的发信号的方式。代码中没有错误,也没有警告。可能是什么问题呢?
7 个回答
我看了你的代码,发现问题出在你连接信号的方式上。
你在Ui_Dialog类里面发出了信号:
self.emit(QtCore.SIGNAL("aa()"))
你在Ui_MainWindow的setupUi方法里连接这个信号,调用的是:
QtCore.QObject.connect(self.loginDialog.ui, QtCore.SIGNAL("aa()"), self.login)
注意,第一个参数变成了self.loginDialog.ui; 你原来的连接调用是用self.loginDialog,这个是LoginDialog类型的,而信号是由Ui_Dialog类发出的,ui属性是LoginDialog的一部分。经过这个修改,Ui_MainWindow的login方法就会被调用了。
希望这能帮到你,祝好!
有一些概念需要澄清
[QT信号与槽] 和 [Python信号与槽]
pyqt提供的所有预定义信号和槽都是用QT的C++代码实现的。每当你想在Python中使用自定义的信号和槽时,那就是Python信号和槽。因此,有四种情况可以将信号发送到槽:
- 从QT信号到QT槽
- 从QT信号到Python槽
- 从Python信号到QT槽
- 从Python信号到Python槽
下面的代码展示了如何连接这四种不同的场景
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Foo(QtCore.QObject):
def __init__(self, parent=None):
super(Foo, self).__init__(parent)
dial = QDial()
self.spinbox = QSpinbox()
# --------------------------------------
# QT signal & QT slot
# --------------------------------------
# option 1: more efficient
self.connect(self.spinbox, SIGNAL("valueChanged(int)"),
dial, SLOT("setValue(int)"))
# option 2:
self.connect(self.spinbox, SIGNAL("valueChanged(int)"),
dial.setValue)
# --------------------------------------
# QT signal & Python slot
# --------------------------------------
self.connect(self.spinbox, SIGNAL("valueChanged(int)"),
self.myValChanged)
# --------------------------------------
# Python signal & Qt slot
# --------------------------------------
# connect option 1: more efficient
self.connect(self, SIGNAL("mysignal"), dial,
SLOT("setValue(int)"))
# connect option 2:
self.connect(self, SIGNAL("mysignal"), dial.setValue)
# emit
param = 100
self.emit(SIGNAL("mysignal"), param)
# --------------------------------------
# Python signal & Python slot
# --------------------------------------
# connect
self.connect(self, SIGNAL("mysignal"), self.myValChanged)
# emit
param = 100
self.emit(SIGNAL("mysignal"), param)
def myValChanged(self):
print "New spin val entered {0}".format(self.spinbox.value())
结论是——
Python信号的签名与QT信号的签名不同,因为它没有括号,并且在你发出信号时可以传递任何Python数据类型。Python信号是在你发出时创建的。
对于槽,有三种签名形式。
- s.connect(w, SIGNAL("信号签名"), 函数名)
- s.connect(w, SIGNAL("信号签名"), 实例.方法名)
- s.connect(w, SIGNAL("信号签名"), 实例, SLOT("槽签名"))
第1和第2种适用于Python槽,而第2和第3种适用于QT槽。很明显,除了QT预定义的槽,任何可调用的Python函数或方法都可以作为Python槽。
这些要点在Summerfield关于信号和槽的文章中有提到。
[旧式QT信号与槽] 和 [新式QT信号与槽]
好吧,上面的描述都是基于旧式的pyqt信号与槽。正如@Idan K所建议的,还有一种新的方式来处理这些事情,特别是对于Python信号。有关更多信息,请参考这里。
在发出信号和连接信号时,你不能用同一个信号。
QtCore.SIGNAL("aa(str)")
和 QtCore.SIGNAL("aa")
是不一样的。信号必须有相同的格式。顺便说一下,如果你自己定义信号,不要定义参数。只需要写 SIGNAL('aa')
,因为定义参数是C++的做法,而Python版本的Qt不需要这样。
所以应该像这样:
QtCore.QObject.connect(self.loginDialog, QtCore.SIGNAL("aa"), self.login)
如果你在发出信号时传递了任何参数,你的登录方法也必须接受这些参数。看看这样是否有帮助 :-)