我有以下代碼在更新UI中的進度條(progress
)時執行後臺操作(scan_value
)。 scan_value
迭代了obj
中的某個值,每次更改該值時都會發出一個信號(value_changed
)。由於這裏不相關的原因,我必須在另一個線程中將其包裝在一個對象(Scanner
)中。掃描儀在按鈕scan
是clicked
時被調用。我的問題來了......以下代碼正常工作(即進度條按時更新)。PyQt:將信號連接到插槽以啓動後臺操作
# I am copying only the relevant code here.
def update_progress_bar(new, old):
fraction = (new - start)/(stop - start)
progress.setValue(fraction * 100)
obj.value_changed.connect(update_progress_bar)
class Scanner(QObject):
def scan(self):
scan_value(start, stop, step)
progress.setValue(100)
thread = QThread()
scanner = Scanner()
scanner.moveToThread(thread)
thread.start()
scan.clicked.connect(scanner.scan)
但是,如果我改變的最後一部分,以這樣的:
thread = QThread()
scanner = Scanner()
scan.clicked.connect(scanner.scan) # This was at the end!
scanner.moveToThread(thread)
thread.start()
進度欄得到僅在結束時更新(我的猜測是,一切都在同一線程上運行)。如果在將對象接收對象移動到線程之前將信號連接到一個插槽之前,它應該是無關緊要的。
看起來像ekhumoro是正確的(pyqt/qt似乎沒有正確地自動檢測連接類型,除非你用@pyqtSlot()明確地修飾你的插槽)。但是,我想指出'progress.setValue(100)'這一行是線程**不安全**,因爲您正在從主線程以外的線程訪問Qt GUI對象。其餘的發佈代碼在Qt GUI操作 –
@three_pineapples方面是線程安全的。知道這裏是否存在PyQt錯誤,或者PyQt如何連接Python可調參數,這將是很有趣的。我知道當不使用'@ pyqtSlot'時會創建某種代理對象,但是對於排隊連接究竟會產生什麼後果,我不知道。 – ekhumoro
@ekhumoro我認爲這可能是一個PyQt4錯誤,或者至少應該糾正一個缺陷。它當然不會在PySide中顯示出相同的行爲(PySide總是在QThread中運行'scan'函數,而不管信號的位置或插槽的位置如何)。我在這裏http://pastebin.com/SqP3WM1z做了一個簡單的例子,它列出了正在運行的線程。 –