我在使用PySide Slot装饰器时遇到了这种奇怪。如果我使用QtCore.Slot修饰我的方法,如果我尝试访问方法中的self.sender(),我会得到None。如果我删除QtCore.Slot()装饰器。我正确地得到了发件人。这是一个最小的例子。
import sys
from PySide.QtCore import *
from PySide.QtGui import *
class Worker(QObject):
def init(self):
print "worker is ready."
@Slot()
def work(self):
print "i am tired, %s" % self.sender()
app = QApplication(sys.argv)
button = QPushButton("Kick!")
button.show()
worker = Worker()
thread = QThread()
worker.moveToThread(thread)
thread.started.connect(worker.init)
button.clicked.connect(worker.work)
# app.connect(button, SIGNAL("clicked()"), worker, SLOT("work()"))
thread.start()
app.exec_()
sys.exit()
但是,如果我将新样式连接更改为旧方式,如注释行所示。
有效。有人可以解释这种行为吗?非常感谢。
答案 0 :(得分:1)
问题是接收信号的对象(您的Worker类)存在于另一个线程中。
来自Qt docs:
QObject * QObject :: sender()const [protected] 如果在由信号激活的槽中调用,则返回指向发送信号的对象的指针;否则它返回0.指针仅在执行从该对象的线程上下文调用此函数的槽期间有效。
如果发件人被销毁,或者插槽与发件人的信号断开连接,此功能返回的指针将变为无效。
警告:此功能违反了面向对象的模块化原则。但是,当许多信号连接到单个插槽时,访问发送器可能很有用。
警告:如上所述,当从与该对象的线程不同的线程通过Qt :: DirectConnection调用插槽时,此函数的返回值无效。在这种情况下不要使用此功能。
如果你没有将对象移动到另一个线程,它可以工作(示例在python3中,但在更改打印行后它将在python 2中工作):
import sys
from PySide.QtCore import *
from PySide.QtGui import *
class Worker(QObject):
def init(self):
print("worker is ready.")
@Slot()
def work(self):
derp = self.sender()
print ("i am tired, {}".format(derp))
derp.setText("It works!")
app = QApplication(sys.argv)
button = QPushButton("Kick!")
button.show()
worker = Worker()
button.clicked.connect(worker.work)
app.exec_()
sys.exit()