PyQt5 QThread запуск гифки вовремя работы функции

Прошу помочь с отображением гифки во время работы функции. В вырезке кода ниже мой набросок кода, в методе interpretation во время длительной работы части программы, хочу отображать гиф-файл, для чего создал экземпляр класса GifThread, который в свою очередь должен работать (отображать пока running не будет присвоено значение False в конце функции interpretation.

Программа повисает, диалог гифки не показывается, хотя с ним вроде все нормально. В коде отметил место "зависания" - это команда показа диалога с гифкой.

Подскажите, пожалуйста, что тут не так.

import os
from PyQt5 import QtCore, QtWidgets, QtSql, QtGui
from PyQt5.Qt import *

class MainWindow(QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()            
        ...

    def initUi(self):
        self.btn2 = QPushButton(self)
        ...

    def connectUi(self):
        self.btn2.clicked.connect(self.interpretation)

    def interpretation(self):
        thread = GifThread(self)
        thread.start()
        ... #<-------довольно длительно выполняющаяся часть кода
        thread.running = False


class GifThread(QtCore.QThread):

    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)
        self.parent = parent
        self.running = False

    def run(self):
        self.running = True
        while self.running:
            gif = GifDialog(self.parent)
            gif.show_gif()


class GifDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(GifDialog, self).__init__(parent)
        self.label_gif = QtWidgets.QLabel(self)
        self.setFixedSize(255, 252)

    @QtCore.pyqtSlot()
    def show_gif(self):
        file_path = os.getcwd() + r"\mgc.gif"
        movie = QtGui.QMovie(file_path, parent=self)
        self.label_gif.setMovie(movie)
        movie.start()
        self.show()  # <----- путем расставления "print"ов выяснил, что вот это не происходит

app = QApplication(sys.argv)
MW = MainWindow()
MW.show()
sys.exit(app.exec_())

Ответы (1 шт):

Автор решения: S. Nick

Вам надо использовать сигналы и слота.

import sys
import os
from PyQt5 import QtCore, QtWidgets, QtSql, QtGui
from PyQt5.Qt import *


class GifThread(QtCore.QThread):
    finish_signal = pyqtSignal()                                          # +++

    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)
        self.running = 0

    def run(self):
        while self.running < 100:
            #   <-------довольно длительно выполняющаяся часть кода
            self.msleep(50)
            self.running += 1
            print(self.running)

        self.finish_signal.emit()                                         # +++  


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()  
        centralWidget = QtWidgets.QWidget()
        self.setCentralWidget(centralWidget)

        self.btn2 = QPushButton("Start", self)
        self.btn2.clicked.connect(self.interpretation)

        self.movie = QMovie(self)                          
        self.movie.setFileName('D:/_Qt/__Qt/img/Fo2BxBK.gif')
        self.movie.jumpToFrame(0)
        self.label = QLabel(self)                               
        self.label.setAlignment(Qt.AlignCenter)
        self.label.setMovie(self.movie)  
        self.label.hide()

        self.thread = GifThread(self)
        self.thread.finish_signal.connect(self.movie_stop)                  # +++

        layout = QVBoxLayout(centralWidget)        
        layout.addWidget(self.label)
        layout.addWidget(self.btn2)

    def movie_stop(self):
        self.movie.stop
        self.label.hide()

    def interpretation(self):
        self.movie.start()
        self.label.show()

        self.thread.running = 0
        self.thread.start()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    MW = MainWindow()
    MW.show()
    sys.exit(app.exec_())

введите сюда описание изображения

→ Ссылка