PySide QtCore.Slot装饰器不能与方法中的self.sender()一起使用

时间:2013-08-02 11:23:08

标签: pyside sender

我在使用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()

但是,如果我将新样式连接更改为旧方式,如注释行所示。

有效。有人可以解释这种行为吗?非常感谢。

1 个答案:

答案 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()