Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QMovie displays GIF with delay.



  • Hi :)
    I try to create Loader screen with GIF showing that data is processed.
    I use PyQT5 and widgets.
    I created QLabel and I set movie on it.
    I works fine when I test it as standalone app.
    But when I use it in my target app dialogs shows up, but animation is loaded after logic processing data is finished. Any other actions made on gui (showing progress bar etc) are not working as well.
    I've read that it is caused by fact that GUI thread is to busy. Is there anything I can do about this?
    Can I start this widget in separate thread?
    I tried to call processEvents() before showing dialog but it does not help.
    Best regards!

    UPDATE: I put processEvents() in few more places during logic processing and it works fine, however I'm not sure if this is good practice to do so manually. Is there better solution?


  • Lifetime Qt Champion

    Hi,

    Looks like your a blocking the event loop with your data processing.

    Without seeing your code is hard to tell but needing to sprinkle calls to processEvent everywhere is sign of a big design issue.



  • Thank you for your response.
    It's quite big application so I can't paste whole code, but I will try to give the essence of it:
    main.py:

    if __name__ == "__main__":
        oldHook = sys.excepthook
        sys.excepthook = catchExceptions
        app = QApplication([])
        engine = ToolEngine()  #inherits from QObject (emits signals and performs main logic, but not as slots, functions are called from another functions created in MainWindow.py
        window = MainWindow(engine)
        window.show()
        # customizing exceptions hook due to fact that some exceptions were not shown in interactive console in PyCharm
        log.debug("App exec")
        retCode = app.exec_()
        sys.exit(retCode)
    

    and file with MainWindow.py:

    class MainWindow(QMainWindow):
        def __init__(self, engine, *args):
            #....
            uic.loadUi(guiPath, self) # quite complex ui file with table, grids etc
            self.backend = engine # can this method of passing backend be a problem? 
            #...
            self.buttonSave.clicked.connect(self.backend.saveChanges)   #function not slot
            self.someButton.clicked.connect(self.someFunction1)  #function not slot
            self.backend.saveStarted.connect(self.showLoadingScreen) #shows QWidget with Label containing QMovie
    
        def someFunction1(self):
            self.backend.doSomeCalculations()
    

    Can you see anything wrong basing on those snippets or thats not clear/enough?


  • Lifetime Qt Champion

    @BigZet said in QMovie displays GIF with delay.:

    self.backend = engine # can this method of passing backend be a problem?

    No, it's just an assignment.

    @BigZet said in QMovie displays GIF with delay.:

    self.backend.saveStarted.connect(self.showLoadingScreen) #shows QWidget with Label containing QMovie

    What I suspect is that the method which emit saveStarted then does a lot of long stuff thus blocking the event loop hence the movie not playing as you'd expect.



  • So I should do this on separate thread to not block GUI thread?


  • Lifetime Qt Champion

    Not knowing what you do in it I can't really comment on whether threading or reworking your code is the best solution.



  • Ok, I understand. Thank you for your help!
    I had so many problems making Python work with widgets that I will probably rewrite it to QML.

    Thanks!


  • Lifetime Qt Champion

    That won't change anything if you are blocking the event loop be it with widgets or QtQuick, you'll have similar issue.

    I highly recommend to fix the blocking parts so you can more freely change the GUI stack if you really want to.


Log in to reply