У меня возникла странная проблема с PyQt5 в Python 3.5. У меня есть два класса, FrontEnd(QWidget)
и TimerThread(Thread)
. У меня есть число QLabel
s, определенное в функции init от FrontEnd
, все из которых работают правильно.PyQt5 Ошибка «Таймеры не могут запускаться из другого потока» при изменении размера QLabel
Показаны соответствующие несколько функций 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)
(front_end
элемент TimerThread
устанавливается на инициализации из 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, я открыт для любых таких предложений).
EDIT:
Это некоторые странные вещи. Я запускал его два раза на следующий день, без изменений кода. (Я думаю ...) Однажды гистограммы не отображались, но ошибок не было. В другой раз я получил это:
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.
Btw, дружелюбный совет, если вы планируете запустить программу PyQt в Windows, убегайте от 'QThread' насколько это возможно. Это приводит к случайным сбоям и приведет вас в бешенство. –
Вы не должны вызывать методы, которые обновляют QObjects [из другого потока] (http://doc.qt.io/qt-5/thread-basics.html#simultaneous-access-to-data). Вы должны создать сигнал, подключить его к слоту, а затем вы можете безопасно испускать этот сигнал из другого потока, обновления будут обрабатываться в цикле событий объекта ['lives'] (http://doc.qt.io/ qt-5/thread-basics.html # qobject-and-threads). – mata
@TheQuantumPhysicist - Нет, если это случается, вероятность того, что вы на самом деле не поняли, как использовать потоки в Qt, и что вы делаете что-то неправильно , Обвинение Qt для ошибок программирования никому не поможет. – mata