Bonjour à tous,

Je code actuellement un logiciel de ticketing pour suivre mon activité.

Ce logiciel charge différents UI en fonction du profil de l'utilisateur ( utilisateur, admin, direction).
Certains de ces profils comportent des appels à des fonction très longues ( interaction avec Outlook pour compter les mails par win32com).

Je cherche à faire en sorte d'afficher un écran de chargement afin que les utilisateurs sachent bien que le logiciel n'a pas planté, mais charge juste le profil.

Pour ce faire, je me suis inspiré d'un script de Tyrtamos ou il montrait comment justement lancer un throbber durant une tache longue grâce au thread.

Mon soucis, c'est que visiblement mes 2 taches ( chargement de l'UI, et affichage du throbber) ne s'effectuent pas en simultané.

Le throbber s'affiche, se fige durant le chargement de l'UI, et recommence à tourner quand l'UI est chargée.


Voici le code

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
 
import sys, os
import time
 
from PyQt5.QtCore import (Qt, QSize, pyqtSlot, pyqtSignal, QThread)
from PyQt5.QtGui import (QMovie)
from PyQt5.QtWidgets import (QApplication, QWidget, QPushButton, QLabel, 
                             QGridLayout)
import Ui_Admin_livrable
import Ui_Direction_livrable
import Ui_User_livrable
from PyQt5 import QtCore
#############################################################################
 
class ThrobberWindow(QLabel):
    """petite fenêtre qui affiche un throbber (image gif animée) pour 
       signaler une activité en cours et faire patienter l'utilisateur
    """
 
    #========================================================================
    def __init__(self, parent=None):
        super(ThrobberWindow, self).__init__(parent)
 
        # image gif animée du throbber
        # configure la fenêtre
        self.setWindowTitle(" ") # supprime le titre de la fenêtre
        self.resize(400, 200) # met une fenêtre carrée
        self.setFixedSize(self.width(), self.height()) # pas de redimensionnement
        # le contenu du QLabel sera au milieu (hor. et vert.)
        self.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
 
        # met seulement un cadre autour de la fenêtre du throbber
        # NB: mais on peut encore la déplacer à la souris!
        newflags = Qt.Dialog
        newflags |= Qt.CustomizeWindowHint  # permet la personnalisation
        newflags &= ~Qt.WindowCloseButtonHint  # pas de case de fermeture
        newflags &= ~Qt.WindowSystemMenuHint  # pas de menu de fenêtre
        newflags &= ~Qt.WindowContextHelpButtonHint # pas de case "?"
        self.setWindowFlags(newflags)
 
        # crée un movie avec le throbber sous forme d'image "gif" animée
        self.movie = QMovie()# j'ai été obligé d'hotter le gif pour des raisons de confidentialité
        self.movie.setScaledSize(QSize(400, 200)) # fixe dimension 
 
        self.setMovie(self.movie) # affecte le movie au QLabel
        self.movie.start() # lance l'animation du throbber
 
 
#############################################################################
class Fenetre(QWidget):
    """fenêtre pour tester le throbber
    """
 
    #========================================================================
    def __init__(self, parent=None):
        super(Fenetre, self).__init__(parent)
 
        self.resize(400, 300)
 
        # créer le bouton
        self.bouton = QPushButton("Lancer le programme!", self)
        self.bouton.clicked.connect(self.lancementprogramme)
 
        # positionne le widget dans la fenêtre
        posit = QGridLayout()
        posit.addWidget(self.bouton, 0, 0)
        self.setLayout(posit)
 
        # pour signaler qu'il n'y a aucun thread en cours
        self.thread = None 
 
 
    #========================================================================
    @pyqtSlot()
    def lancementprogramme(self):
        """slot exécuté lors du clic sur le bouton: lance le thread
        """
        if self.thread != None:
            return # il y a déjà un thread en cours: on ne fait rien
 
        self.throbber_worker=QtCore.QThread()
        self.throbber_worker.start()
 
        # crée le throbber
        self.throbber = ThrobberWindow()
        # option: met la fenêtre du throbber en mode "modal"
        self.throbber.setWindowModality(Qt.ApplicationModal)
        # affiche la petite fenêtre du throbber
        self.throbber.show()
 
        # lance le thread
        self.worker=QtCore.QThread()
        self.worker.start()
 
        self.thread = threading()
        self.thread.moveToThread(self.worker)
        self.thread.close_open_UI_admin()
 
    #========================================================================
 
class threading (QtCore.QObject):
 
        def __init__(self, parent=None):
            super(threading, self).__init__(parent)
 
        def close_open_UI_admin(self):
            """ferme la fenetre et lance l'environnement choisi"""
            self.UI_admin=Ui_Admin_livrable.App_Admin()
            self.UI_admin.setWindowModality(QtCore.Qt.ApplicationModal)
            self.UI_admin.show()
 
 
 
 
#############################################################################
if __name__ == "__main__":
    app = QApplication(sys.argv)
    fen = Fenetre()
    fen.show()
    sys.exit(app.exec_())
Je vous joins également le constructeur du module dont hérite "App_admin" afin de savoir si le soucis de vient pas d'elle.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
class App_Admin(QtWidgets.QWidget):
    def __init__(self):
 
        super().__init__()
        self.setWindowTitle("test")   
        self.resize(1000,1050)
        self.move(1500,100)
        self.setup_UI()
        self.setStyleSheet("font: 10pt;")
        self.timer_modif()
 
 
    def setup_UI(self):
En tant qu'autodidacte, si vous avez des conseils, remarques, bonnes pratiques, je suis preneur !
De même, si vous connaissez de bonnes ressources pour me former correctement au Threading, je suis également preneur ( j'ai passé de nombreuses heures à chercher du contenu clair ).