为什么使用QThread无法显示我的加载屏幕?

问题描述 投票:0回答:1

我正在制作一个桌面应用程序,一旦数据库被加载,我要显示一个加载屏幕。一个简单的搜索使我在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的实现肯定存在问题。

python multithreading pyqt pyqt5 qthread
1个回答
0
投票

您的代码有几个问题。正如@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()
© www.soinside.com 2019 - 2024. All rights reserved.