2013-08-02 59 views
0

我在使用PySide Slot修飾器時遇到了這種奇怪現象。如果我使用QtCore.Slot來裝飾我的方法,並且如果我嘗試訪問方法內部的self.sender(),我會得到None。如果我刪除了QtCore.Slot()裝飾器。我正確地得到發件人。這是一個簡單的例子。PySide QtCore.Slot修飾器不能在方法內使用self.sender()

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

問題是接收信號的對象(您的Worker類)存在於另一個線程中。

從Qt的文檔:

的QObject *的QObject ::發送者()const的[保護] 將指針返回到發送信號中,如果在調用由信號激活一個時隙中的對象;否則返回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() 
+0

對不起因爲我在度假時已經遲到了。你是對的。我不應該從不同的線程調用。但是,我仍然懷疑新舊風格的差異。我認爲它們是相同的,但事實上並非如此。也許這是無證行爲? – foresightyj

+0

那麼,他們是相當的(據我所知)。唯一的區別是,新風格更加pythonic。舊的方式是如何在C++中完成。 來源:http://qt-project.org/wiki/Signals_and_Slots_in_PySide – Angel

+0

是的。這是我閱讀信號和插槽文檔時的想法。在我的情況下,我必須使用線程(用於長時間後臺處理),我現在的解決方案是使用舊式連接。我感覺不好,因爲我的代碼是魔術......請注意,在我的情況下,刪除插槽裝飾器或使用舊式連接工作。 – foresightyj