【发布时间】:2017-07-10 12:07:33
【问题描述】:
我在 Python 3.5 中遇到了一个奇怪的 PyQt5 问题。
我有两个班级,FrontEnd(QWidget) 和 TimerThread(Thread)。我在FrontEnd的init函数中定义了多个QLabels,都可以正常工作。
显示的是FrontEnd的相关几个函数:
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 类:
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)
(TimerThread 的 front_end 元素在 FrontEnd 的初始化时设置)
问题出在update_bar_graph 函数中。当setFixedSize 调用被注释掉时,程序运行良好,尽管没有在我的应用程序中正确显示条形图的条(它们是QLabels)。 move 函数似乎运行正常。但是,setFixedSize 调用会导致此错误:
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
我完全不知道为什么会发生这种情况,也不知道为什么 move 函数在性质上看似相似,但工作正常。任何帮助将非常感激。
(如果我应该使用不同类型的计时器类或不同的方法在 PyQt 中绘制大矩形,我愿意接受任何此类建议)。
编辑:
这是一些奇怪的东西。第二天我运行了两次,没有更改代码。 (我认为...)有一次条形图没有显示,但没有引发错误。另一次我得到了这个:
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 中发现了一个错误。
【问题讨论】:
-
顺便说一句,一个友好的建议,如果您打算在 Windows 上运行 PyQt 程序,请尽可能远离
QThreads。它会导致随机崩溃,会让你发疯。 -
你不应该调用更新 QObjects from a different thread 的方法。您应该创建一个信号,将其连接到一个插槽,然后您可以安全地从另一个线程发出该信号,更新将在对象 'lives' 中的事件循环中处理。
-
@TheQuantumPhysicist - 不,如果发生这种情况,可能是您还没有真正了解如何在 Qt 中使用线程并且您做错了什么。将编程错误归咎于 Qt 对任何人都没有帮助。
-
@mata 我使用 Qt 已经 6 年了。我不是新手。 C++ 上的 QThread 很好。但是 Python 上的 QThread 充满了 bug。欢迎您尝试自己并承担后果。不仅我为此受苦,而且我还询问了许多不同的人随机崩溃,并且背后总是有一个 QThread。我什至对它进行了 WinGDB 调试,发现 QThread 是万恶之源。你可以试着对我抱理想主义,并声称我错的可能性更大,但只有在你像我一样浪费了一些美好的时光之后,你才会知道真相。万岁多处理!
-
@TheQuantumPhysicist 你有任何具体的例子/证据来支持你的说法吗?我很想看到崩溃的最小工作示例。我见过 Pyside 做坏事,但如果代码实际上是线程安全的,PyQt 从来没有给我带来麻烦。如果您没有证据可以提出与发布的特定问题相关的证据,那么我真的不认为随机问题的 cmets 是提出此类指控的地方。
标签: python multithreading timer pyqt pyqt5