Home > Mobile >  Using PyQt5 splash screen to cover module load time
Using PyQt5 splash screen to cover module load time

Time:04-04

I have created a GUI that loads a library my_lib which depends on a number of heavy modules. It will be converted to an executable using PyInstaller.

I would like to create a splash screen to hide the long (more than 5 seconds) loading time.

One method is to use the --splash parameter of PyInstaller, but this will be independent of the program and works using a timer.

The other method is to create splash screen using PyQt5. Here's a sample of the main script:

# various imports including standard library and PyQt.
from my_lib import foo, bar, docs_url, repo_url


class MainWindow(QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.action_docs.triggered.connect(lambda x: QDesktopServices.openUrl(QUrl(docs_url)))
        self.action_code.triggered.connect(lambda x: QDesktopServices.openUrl(QUrl(repo_url)))

    def show_splash(self):
        self.splash = QSplashScreen(QPixmap("path\to\splash.png"))
        self.splash.show()
        # Simple timer to be replaced with better logic.
        QTimer.singleShot(2000, self.splash.close)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle(QStyleFactory.create('fusion'))
    main = MainWindow()
    main.show()
    main.show_splash()
    sys.exit(app.exec_())

The problem with the above code is that the import is done at the top and then the splash screen is opened which defeats the point. Also, the definition for MainWindow class depends on the objects imported from my_lib.

How can I hide the loading time of the heavy modules when the basic definitions of the GUI depends on them? Is there I'm something missing? Is it even possible?

CodePudding user response:

Edit: This approach is unnecessary. As @musicamante noted in the comments, the above (edited) example raises no errors and can be used without any problems.


After considering the comment by @musicamante, I had the idea to divide the logic in the __ main __ conditional into two pieces. One before the heavy imports and the other in the end. So it goes like this:

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle(QStyleFactory.create('fusion'))
    splash_object = QSplashScreen(QPixmap("path\to\splash.png"))
    splash_object.show()

#
# Load the heavy libraries, including my_lib.
#

class MainWindow(QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

if __name__ == '__main__':
    splash_object.close()
    main = MainWindow()
    main.show()
    sys.exit(app.exec_())

This seems to work very well, but I'm not sure about any side effects of this split.

It should be noted that much of the startup time seems to be from the unpacking of the executable file.

Edit: This answer suggests a similar approach.

  • Related