PyQt5 “Timers cannot be started from another thread” error when changing size of QLabel
我在Python 3.5中遇到了PyQt5的奇怪问题。
我有两个类,
显示的是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | def update_ui(self): ret, frame = self.cam_capture.read() if self.results_pending: if not path.isfile('output.jpg'): self.results_pending = False with open('.out') as content_file: content = content_file.readlines()[2:-2] system('rm .out') self.handle_image_classification(content) if self.take_picture: cv2.imwrite('output.jpg', frame) self.user_prompt.setText('Please wait...') system('./classifyimage.py --mean mean.binaryproto --nogpu --labels labels.txt model.caffemodel deploy.prototxt output.jpg > .out && rm output.jpg') self.take_picture = False self.results_pending = True image = QImage(frame, frame.shape[1], frame.shape[0], QImage.Format_RGB888).rgbSwapped() pix = QPixmap.fromImage(image) self.video_frame.setPixmap(pix) def update_bar_graph(self, data): palette = QPalette() palette.setColor(QPalette.Background, Qt.white) for i in range(0, 8): self.bar_graph_labels[i].setText(str(data[i]) +"%") height = int(data[i] * 5) self.bar_graph[i].setFixedSize(self.bar_width, height) self.bar_graph[i].move(1280 + (i * (self.bar_width + self.bar_spacing)), 640 - height) def handle_image_classification(self, raw_output): data = [None] * 8 for i in range(0, len(raw_output)): raw_output[i] = raw_output[i].strip() data[int(raw_output[i][-2]) - 1] = float(raw_output[i][:-10]) self.update_bar_graph(data) |
而整个TimerThread类:
1 2 3 4 5 6 7 8 9 10 | class TimerThread(Thread): front_end = None def __init__(self, event): Thread.__init__(self) self.stopped = event def run(self): while not self.stopped.wait(0.02): FrontEnd.update_ui(self.front_end) |
(
问题出在
1 2 3 4 | QObject::startTimer: Timers cannot be started from another thread QObject::startTimer: Timers cannot be started from another thread QObject::killTimer: Timers cannot be stopped from another thread QObject::startTimer: Timers cannot be started from another thread |
我完全不知道为什么会发生这种情况,为什么
(如果我应该使用不同类型的计时器类或不同的方法在PyQt中绘制大矩形,我愿意接受任何这样的建议)。
编辑:
这是一些奇怪的东西。我第二天跑了两次,代码没有变化。 (我想......)有一次条形图没有显示但没有抛出任何错误。另一次我得到了这个:
1 2 3 4 5 6 7 8 9 | 7fdfaf931000-7fdfaf932000 r--p 0007a000 08:07 655633 /usr/lib/x86_64-linux-gnu/libQt5DBus.so.5.5.1 7fdfaf932000-7fdfaf933000 rw-p 0007b000 08:07 655633 /usr/lib/x86_64-linux-gnu/libQt5DBus.so.5.5.1 7fdfaf933000-7fdfaf934000 rw-p 00000000 00:00 0 7fdfaf934000-7fdfaf971000 r-xp 00000000 08:07 667112 /usr/lib/x86_64-linux-gnu/libxkbcommon.so.0.0.0 7fdfaf971000-7fdfafb70000 ---p 0003d000 08:07 667112 /usr/lib/x86_64-linux-gnu/libxkbcommon.so.0.0.0 7fdfafb70000-7fdfafb72000 r--p 0003c000 08:07 667112 /usr/lib/x86_64-linux-gnu/libxkbcommon.so.0.0.0 7fdfafb72000-7fdfafb73000 rw-p 0003e000 08:07 667112 /usr/lib/x86_64-linux-gnu/libxkbcommon.so.0.0.0 7fdfafb73000-7fdfafb7a000 r-xp 00000000 08:07 667110 /usr/lib/x86_64-linux-gnu/libxkbcommon-x11.so.0.0.0 7fdfafb7a000-7fdfafd79000 ---p 00007000 08:07 667110 /usr/lib/x86_64-linux-gnu/libxkbcommon-x11.so.0.0.0 |
我想我可能在PyQt5中发现了一个错误。
正如@mata所提到的,您的代码不是线程安全的。这可能是错误行为的来源,并且应该在进一步调试之前确定(这是相关的)。
它是线程不安全的原因是因为您直接从辅助线程与GUI对象进行交互。您应该从线程向主线程中的插槽发出信号,您可以安全地更新GUI。但是,这需要您使用
这需要进行以下更改:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class TimerThread(QThread): update = pyqtSignal() def __init__(self, event): QThread.__init__(self) self.stopped = event def run(self): while not self.stopped.wait(0.02): self.update.emit() class FrontEnd(QWidget): def __init__(self): super().__init__() ... # code as in your original stop_flag = Event() self.timer_thread = TimerThread(stop_flag) self.timer_thread.update.connect(self.update_ui) self.timer_thread.start() |
我还修改了你的代码,以便它存储对
我还要补充一点,这是一种每0.02秒触发更新的过于复杂的方式。您可以使用