为什么我的加载屏幕没有使用 QThread 显示?

Why is my loading screen not showing up using 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.[=14= 实现肯定有问题]

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