我正在制作一个桌面应用程序,一旦数据库被加载,我要显示一个加载屏幕。一个简单的搜索使我在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
的实现肯定存在问题。
您的代码有几个问题。正如@musicamante所说,您不能在主线程之外创建小部件。这意味着您无法在myThread.run
中创建对话框。相反,您可以将对话框的管理移至Main
,并使用插槽和信号打开和关闭对话框。
第二,所有耗时的任务,例如time.sleep(5)
,都应放在myThread.run
中。
考虑到这一点,你可以做这样的事情
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):
# time consuming actions
time.sleep(5)
class Main(QWidget):
def __init__(self):
super().__init__()
print('Thread is to be called here...')
self.load()
print('Thread has been called...')
btn= QPushButton('Test button')
vbox = QVBoxLayout()
vbox.addWidget(btn)
self.setLayout(vbox)
self.show()
def load(self):
# setup dialog
dialog = QDialog(self)
vbox = QVBoxLayout()
lbl = QLabel(self)
self.moviee = QMovie('Loading.gif')
lbl.setMovie(self.moviee)
self.moviee.start()
vbox.addWidget(lbl)
dialog.setLayout(vbox)
# setup thread
thread = myThread()
thread.finished.connect(thread.deleteLater)
thread.finished.connect(dialog.close)
thread.finished.connect(dialog.deleteLater)
thread.start()
dialog.exec()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Main()
app.exec()