首页 > 解决方案 > 为什么我的加载屏幕没有使用 QThread 显示?

问题描述

我正在制作一个桌面应用程序,一旦加载数据库,我想显示一个加载屏幕。一个简单的搜索让我在 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.

标签: pythonmultithreadingpyqtpyqt5qthread

解决方案


您的代码有几个问题。正如@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()

推荐阅读