【发布时间】:2020-07-25 11:54:07
【问题描述】:
我正在制作一个桌面应用程序,一旦数据库被加载,我想显示一个加载屏幕。一个简单的搜索让我在 QLabel 中使用带有 QThread 对象的 gif 文件。但就我而言,QThread 不会显示任何内容。 该线程工作正常,但我的实现有问题,我无法弄清楚是什么。我的示例代码如下:
from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QDialog, QApplication, QPushButton
from PyQt5.QtCore import QThread
from PyQt5.QtGui import QMovie
import sys
import time
class myThread(QThread):
def run(self):
test = QWidget() # Only creating this to give parent to QDialog and QLabel objects in upcoming lines
dialog = QDialog(test)
vbox = QVBoxLayout()
lbl = QLabel(test)
self.moviee = QMovie('Loading.gif')
lbl.setMovie(self.moviee)
self.moviee.start()
vbox.addWidget(lbl)
dialog.setLayout(vbox)
dialog.show()
def stop(self):
self.moviee.stop()
class Main(QWidget):
def __init__(self):
super().__init__()
print('Thread is to be called here...')
thread = myThread()
thread.run()
print('Thread has been called...')
btn= QPushButton('Test button')
vbox = QVBoxLayout()
vbox.addWidget(btn)
self.setLayout(vbox)
time.sleep(5) # sleep function used to emulate funcitons in actual program
# thread.stop()
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Main()
sys.exit(app.exec_())
带有QMovie 对象的代码块在Main 循环中工作正常,所以我的QThread 实现肯定有问题。
【问题讨论】:
-
您是否尝试调用
thread.run(),但QThread 只能通过start()启动。 doc.qt.io/qtforpython/PySide2/QtCore/… -
不应在主 Qt 线程之外发生 GUI 元素访问(包括创建)。不应在主 Qt 线程中发生任何阻塞函数(例如对
sleep的调用)。 QThreads 正是那些必须被实现和用来完成“繁重工作”的线程,与 GUI 相关的所有内容都应该在主 Qt 线程中,而不是相反。 -
@VladimirBershov
thread.run()方法也是如此。没有线索。 -
@AsadUllahButt 你不能在非主线程中创建 GUI 元素。这行不通。
-
@AsadUllahButt 假设您已经更正了 Vladimir 报告的内容(该线程应该通过调用
start()开始),由于我之前告诉过的原因,它无法完全正确工作:QMovie与 QLabel 交互,它是一个 GUI 对象,因此必须始终只能从主 Qt 线程访问。您不能从另一个线程创建/访问/修改 QWidget(包括在 QLabel 中播放 QMovie)。您必须在主线程中离开创建 QLabel和播放 QMovie。这就是 Qt 的工作方式(一个,AFAIK,就像所有基于 GUI 的框架一样)。
标签: python multithreading pyqt pyqt5 qthread