PySide QtCore.Slot decorator does not work with self.sender() inside a method

依然范特西╮ 提交于 2019-12-08 11:20:50

问题


I came across this weirdness in using PySide Slot decorator. If I decorate my method using QtCore.Slot and if I try to access self.sender() inside the method, I get None. If I remove the QtCore.Slot() decorator. I get the sender properly. Here is a minimal example.

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

However, if I change the new style connection to the old way, as shown in the commented line.

It works. Can someone explain this behavior? Thanks a lot.


回答1:


The problem is that the object that receive the signal (your Worker class) lives in another thread.

From the Qt docs:

QObject * QObject::sender () const [protected] Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; otherwise it returns 0. The pointer is valid only during the execution of the slot that calls this function from this object's thread context.

The pointer returned by this function becomes invalid if the sender is destroyed, or if the slot is disconnected from the sender's signal.

Warning: This function violates the object-oriented principle of modularity. However, getting access to the sender might be useful when many signals are connected to a single slot.

Warning: As mentioned above, the return value of this function is not valid when the slot is called via a Qt::DirectConnection from a thread different from this object's thread. Do not use this function in this type of scenario.

If you don't move the object to the other thread, it works (the examples is in python3, but it will work in python 2, after changing the print lines):

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


来源:https://stackoverflow.com/questions/18015684/pyside-qtcore-slot-decorator-does-not-work-with-self-sender-inside-a-method

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!