在这个简单的例子中我想要:
当我运行我的文件时,它工作正常,但显示:
QObject::killTimer: Timers cannot be stopped from another thread
我是 PyQT 新手,我不知道如何解决这个问题。
使用
threading.Thread
是否有意义,或者我应该使用QThread
对于我的用例,或者一些完全不同的代码组织?
使用线程来不阻塞 GUI 是常见的还是我在重新发明轮子?
from PySide6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QPushButton, QLabel
)
from PySide6.QtCore import QTime, QTimer
import threading
import time
class MyWindow(QWidget):
def __init__(self):
super().__init__()
self.resize(200, 100)
self.button = QPushButton('Do work', self)
self.button.clicked.connect(self.run_work_thread)
self.timer_label = QLabel('', self) # hide label at the start (but save its space)
layout = QVBoxLayout(self)
layout.addWidget(self.button)
layout.addWidget(self.timer_label)
self.setLayout(layout)
def run_work_thread(self):
"""Do work in a separate thread, not to block the GUI"""
self.button.setEnabled(False)
thread = threading.Thread(target=self.do_work)
thread.start()
self.start_time = QTime(0, 0, 0)
self.timer = QTimer(self)
self.timer_label.setText('Doing work for: 0 s')
self.timer.timeout.connect(self.update_timer)
self.timer.start(1000) # update every 1 sec
def do_work(self):
time.sleep(2) # Simulate work
self.timer.stop()
self.timer_label.setText('') # clear the timer label
self.button.setEnabled(True)
def update_timer(self):
"""Update the timer, and its label with the elapsed time"""
self.start_time = self.start_time.addMSecs(1000)
self.timer_label.setText(f'Doing work for: {self.start_time.toString("s")} s')
if __name__ == '__main__':
app = QApplication([])
window = MyWindow()
window.show()
app.exec()
按照@musicamante的有用建议,这是我所做的解决方案:
from PySide6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QPushButton, QLabel
)
from PySide6.QtCore import QTime, QTimer, QThread, Signal
import time
class Worker(QThread):
finished = Signal() # Signal to indicate the work is done
def run(self):
time.sleep(2) # Simulate work
self.finished.emit() # Emit the finished signal
class MyWindow(QWidget):
def __init__(self):
super().__init__()
self.resize(200, 100)
self.button = QPushButton('Do work', self)
self.button.clicked.connect(self.run_work)
self.timer_label = QLabel('', self)
layout = QVBoxLayout(self)
layout.addWidget(self.button)
layout.addWidget(self.timer_label)
self.setLayout(layout)
### ADDED: ###
self.worker = Worker()
self.worker.finished.connect(self.on_work_finished)
##############
def run_work(self):
"""Start the work and the timer"""
self.button.setEnabled(False)
self.start_time = QTime(0, 0, 0)
self.timer = QTimer(self)
self.timer_label.setText('Doing work for: 0 s')
self.timer.timeout.connect(self.update_timer)
self.timer.start(1000) # update every 1 sec
self.worker.start()
def on_work_finished(self):
"""Stop the timer and reset the UI when work is done"""
self.timer.stop()
self.timer_label.setText('')
self.button.setEnabled(True)
def update_timer(self):
"""Update the timer and its label with the elapsed time"""
self.start_time = self.start_time.addSecs(1)
self.timer_label.setText(f'Doing work for: {self.start_time.toString("s")} s')
if __name__ == '__main__':
app = QApplication([])
window = MyWindow()
window.show()
app.exec()