2

I am developing an app that when started needs to check various things like if the modules are found, if a connection to a microcontroller is working, etc. So I decided to make a splash screen where each of these steps show a message. What I thought was to make several images that have the text saying ('Loading modules...'), ('Checking connection...') and change them everytime the step is being run. The following code is what I thought of:

images = ["path1", "path2", ...]
app = QApplication(sys.argv)

for i in images:
   pixmap = QPixmap(i)
   splash = QSplashScreen(pixmap)

   splash.show()
   QTimer.singleShot(3000, splash.close) #the timer is just to pretend some process is running
   app.processEvents()
   app.exec_()

This code only shows the last of the images, not each separated by 3 seconds. Any clue on how I can fix this?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241

1 Answers1

1

You must create signals that indicate the states and change the images:

import sys

from PyQt5 import QtCore, QtGui, QtWidgets


class Manager(QtCore.QObject):
    """Class that simulates the loading steps"""

    started = QtCore.pyqtSignal()
    loaded_modules = QtCore.pyqtSignal()
    connected = QtCore.pyqtSignal()
    finished = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent)

    def start(self):
        self.started.emit()
        for i, step in enumerate((self.loaded_modules, self.connect, self.finish), 1):
            QtCore.QTimer.singleShot(i * 2000, step)

    def load_modules(self):
        self.loaded_modules.emit()

    def connect(self):
        self.connected.emit()

    def finish(self):
        self.finished.emit()


class SplashScreen(QtWidgets.QSplashScreen):
    @QtCore.pyqtSlot()
    def handle_started(self):
        self.show()
        self.setPixmap(QtGui.QPixmap("started.png"))

    @QtCore.pyqtSlot()
    def handle_loaded_modules(self):
        self.setPixmap(QtGui.QPixmap("loaded_modules.png"))

    @QtCore.pyqtSlot()
    def handle_connected(self):
        self.setPixmap(QtGui.QPixmap("connected.png"))

    @QtCore.pyqtSlot()
    def handle_finished(self):
        self.close()


def main():
    app = QtWidgets.QApplication(sys.argv)

    w = QtWidgets.QMainWindow()
    w.resize(640, 480)

    manager = Manager()
    splash_screen = SplashScreen()

    manager.started.connect(splash_screen.handle_started)
    manager.loaded_modules.connect(splash_screen.handle_loaded_modules)
    manager.connected.connect(splash_screen.handle_connected)
    manager.finished.connect(splash_screen.handle_finished)
    manager.finished.connect(w.show)

    manager.start()

    app.exec_()


if __name__ == "__main__":
    main()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thank you, this worked! If I want to start the main window of my program after the splash screen has done its thing, where do I place the code to make it start? I placed it after manager.start() and it doesn't run the splash screen anymore. – Bernardo Santos Dias Jul 19 '20 at 22:02
  • 1
    @BernardoSantosDias in my example as you see "w" is the main window that I created from the beginning, and I use the finished Manager signal to show it. – eyllanesc Jul 19 '20 at 22:04
  • Oh sorry, that detail escaped me. I was reading the QSplashScreen documentation and got stuck on their example on how to open the window. It worked, thank you very much! – Bernardo Santos Dias Jul 19 '20 at 22:16