IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

GUI Python Discussion :

[Kivy] Affichage "dynamique" pendant qu'un process s'execute en Arrière plan [Python 2.X]


Sujet :

GUI Python

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2017
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2017
    Messages : 53
    Points : 32
    Points
    32
    Par défaut [Kivy] Affichage "dynamique" pendant qu'un process s'execute en Arrière plan
    Bonjour à tous,

    Dans l'appli Kivy que je développe (sur Raspberry + écran tactile), Je souhaite lorsque je quitte l'application générer un graphe avec matplotlib.

    Problème

    La génération de ce(s) graphe(s) met une 20aine de secondes. Pendant ce temps l'appli Kivy "freeze", une fois le graph generé, celle-ci peut enfin se quitter. Met l'utilisateur voir un écran qui ne répond pas pendant au moins 15 secondes, sans aucune informations...

    Solution
    Informer l'utilisateur, et c'est là que ça coince... j'ai essayé avec un pop up Kivy, avec un Label qui apparaitrait à ce moment donné, mais rien ne semble fonctionner...

    Mon 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
        def fermerBanc(self):  
     
          [...]
     
            if(passerelle.graph1.flagGraph):
     
                p1 = Process(target=process_graph, args=(list_argument_graph_1,))
                p2 = Process(target=process_graph, args=(list_argument_graph_2,))
                p3 = Process(target=process_graph, args=(list_argument_graph_3,))
                p4 = Process(target=process_graph, args=(list_argument_graph_4,))
     
                try:
                    p1.start()
                except AttributeError:
                    Logger.warning('fermerBanc: impossible de generer un graph 1, fichier vide')
     
                try:
                    p2.start()  
                    pass
                except AttributeError:
                    Logger.warning('fermerBanc: impossible de generer un graph 2, fichier vide')
     
                try:
                    p3.start()
                    pass
                except AttributeError:
                    Logger.warning('fermerBanc: impossible de generer un graph 3, fichier vide')
     
                try:
                    p4.start()
                    pass              
                except AttributeError:
                    Logger.warning('fermerBanc: impossible de generer un graph 4, fichier vide')
     
                self.msgWarning = Label(text="Merci de patienter...", font_size='55sp', size=(100, 50), pos_hint={'center_x': .5, 'center_y':.5})
                self.add_widget(self.msgWarning)
     
                p1.join()
                p2.join()
                p3.join()
                p4.join()
     
            exit()
    Merci d'avance !!

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Si vous lancez vos process et que vous attendez qu'ils se terminent avant de rendre la main à Kivy, l'affichage restera gelé... (comme avec n'importe quelle interface graphique).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2017
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2017
    Messages : 53
    Points : 32
    Points
    32
    Par défaut
    J'avais aussi essayé :

    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
      passerelle.start_stop = 0
     
            self.msgWarning = Label(text="Merci de patienter...", font_size='55sp', size=(100, 50), pos_hint={'center_x': .5, 'center_y':.5})
            self.add_widget(self.msgWarning)
     
     
        [...]
     
     
            if(passerelle.graph1.flagGraph):
                # t1=Thread_graph(chemin=chemin1, y_low_min=passerelle.graph1.y_low_min, y_low_max=passerelle.graph1.y_low_max, y_high_min=passerelle.graph1.y_high_min, y_high_max=passerelle.graph1.y_high_max, format_graph=passerelle.graph1.setTaille)
                # t2=Thread_graph(chemin=chemin2, y_low_min=passerelle.graph1.y_low_min, y_low_max=passerelle.graph1.y_low_max, y_high_min=passerelle.graph1.y_high_min, y_high_max=passerelle.graph1.y_high_max, format_graph=passerelle.graph1.setTaille)
                # t3=Thread_graph(chemin=chemin3, y_low_min=passerelle.graph1.y_low_min, y_low_max=passerelle.graph1.y_low_max, y_high_min=passerelle.graph1.y_high_min, y_high_max=passerelle.graph1.y_high_max, format_graph=passerelle.graph1.setTaille)
                # t4=Thread_graph(chemin=chemin4, y_low_min=passerelle.graph1.y_low_min, y_low_max=passerelle.graph1.y_low_max, y_high_min=passerelle.graph1.y_high_min, y_high_max=passerelle.graph1.y_high_max, format_graph=passerelle.graph1.setTaille)
                p1 = Process(target=process_graph, args=(list_argument_graph_1,))
     
                p2 = Process(target=process_graph, args=(list_argument_graph_2,))
     
                p3 = Process(target=process_graph, args=(list_argument_graph_3,))
     
                p4 = Process(target=process_graph, args=(list_argument_graph_4,))
     
     
                try:
                    p1.start()
     
     
                except AttributeError:
                    Logger.warning('fermerBanc: impossible de generer un graph 1, fichier vide')
     
                try:
                    p2.start()
     
                    pass
     
                except AttributeError:
                    Logger.warning('fermerBanc: impossible de generer un graph 2, fichier vide')
     
                try:
                    p3.start()
     
                    pass
                except AttributeError:
                    Logger.warning('fermerBanc: impossible de generer un graph 3, fichier vide')
     
                try:
                    p4.start()
     
                    pass              
                except AttributeError:
                    Logger.warning('fermerBanc: impossible de generer un graph 4, fichier vide')
     
     
     
                p1.join()
                p2.join()
                p3.join()
                p4.join()
     
     
     
     
     
            exit()
    Mais ça ne change rien...


    EDIT : commenter la ligne me donne le résultat suivant :
    -le programme génère les graphes PUIS affiche le "Merci de patienter..." Même si le "add_widget" est au début de ma fonction. J'ai l'impression que peu importe ou se situe mon ajout du label sur l'écran dans le code, celui ci s'effectuera à la fin de ma fonction...

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Citation Envoyé par StanSmooth Voir le message
    J'avais aussi essayé :
    ...
    Mais ça ne change rien...
    Normal, vous pourriez aussi remplacer vos process par un time.sleep(...), vous auriez le même résultat: interface bloquée.
    Un interface graphique, c'est une programmation pilotée par les événements qui iront déclencher des callbacks... fonctions qui devront se terminer le plus rapidement possible pour que l'interface reste réactive.
    Ça a des conséquences sur la façon de programmer.
    Et Kivy n'est pas la bibliothèque graphique qui permet au débutant d'appréhender facilement tout çà: vous êtes supposé le savoir "avant" (et l'avoir appris en utilisant des bibliothèques plus simples ) ainsi que d'être à l'aise avec la POO.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2017
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2017
    Messages : 53
    Points : 32
    Points
    32
    Par défaut
    Très bien mais dans ce cas comment contourner ce problème ? Je ne pense pas que supprimer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
                p1.join()
                p2.join()
                p3.join()
                p4.join()
    Soit une bonne idée, puisque une fois mon appli kivy quitté, j'aurais des process "en liberté", et que je souhaite que l'utilisateur reste dans l'interface kivy tant que les graphes ne sont pas generés.

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Citation Envoyé par StanSmooth Voir le message
    Très bien mais dans ce cas comment contourner ce problème ?
    Vous ne pouvez rien contourner, juste apprendre à faire avec.
    Et le sujet étant comment intégrer dans son application Kivy des activités asynchrones, vous pouvez essayer de vous inspirer de cet article du Wiki de Kivy (ou chercher par vous même des solutions sur Internet).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 461
    Points : 9 248
    Points
    9 248
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Je ne connais pas kivy, mais j'ai déjà eu ce type de problème avec PyQt5, et voilà une des solutions que j'ai utilisée:

    En fait, un graphique "non-gelé" est un graphique qui exécute la boucle de traitement des évènements. Et quand le programme est en train d'attendre quelque chose, cette boucle n'est pas traitée et le graphique n'écoute rien (ni clavier, ni souris, ...).

    Il faut donc supprimer les .join(), qui sont justement là pour attendre. Mais dans ce cas, le graphique ne sera pas gelé, mais il "ne saura pas" quand les données seront disponibles pour affichage.

    On va donc les remplacer par une boucle while qui va tester si les processus sont toujours en activité (is_alive()), et si oui, redonner la main au graphique, attendre un peu (sleep(0.2)) et recommencer la boucle. Cette boucle sera arrêtée quand les 4 processus seront terminés. Quelque chose comme ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    while p1.isalive() or p2.isalive() or p3.isalive() or p4.isalive():
        redonner la main au graphique
        time.sleep(0.5)
    récupérer les données et les afficher
    Reste à savoir comment avec kivy on peut redonner la main au graphique pour qu'il traite les évènements en attente! Et là, il faut chercher: ça doit exister. Dans la doc, bien sûr, mais quelquefois, on trouve ça plus facilement dans les exercices sur le web. Avec PyQt5, c'est "QtCore.QCoreApplication.processEvents()".
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2017
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2017
    Messages : 53
    Points : 32
    Points
    32
    Par défaut
    Salut tyrtamos,

    Merci beaucoup de ta réponse, qui a su bien m'orienter dans mes recherches. J'ai au final appliqué une solution un peu différente mais tout est parti de ton aide !

    Il "suffisait" d'utiliser la fonction Clock.schedule_once de Kivy de cette manière :

    -Mon bouton "quitter"" appelle une nouvelle fonction "fermerBanc_schedule" : celle ci crée mon label "merci de patienter", puis appelle via schedule once ma fonction de base "fermerbanc". de cette manière, le label est affiché avant (et pendant) la géneration de mes graphes au format .png !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def fermerBanc_schedule(self, *args):
            self.msgWarning = Label(text="Merci de patienter...", font_size='55sp', size=(100, 50), pos_hint={'center_x': .5, 'center_y':.5})
            self.add_widget(self.msgWarning)
            Clock.schedule_once(lambda dt: self.fermerBanc(self, *args), 0)
    Le thread qui m'a eclairé
    la doc en question

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. affichage statistique "dynamique"
    Par nezdeboeuf62 dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 13/04/2007, 14h05
  2. probléme affichage images dynamiques
    Par abdelfettah2007 dans le forum Langage
    Réponses: 1
    Dernier message: 15/03/2007, 00h20
  3. Affichage courbe dynamique
    Par Polux95 dans le forum Qt
    Réponses: 11
    Dernier message: 14/03/2007, 13h37
  4. [FLASH MX2004] Pb d'affichage texte dynamique
    Par mohican13 dans le forum Flash
    Réponses: 6
    Dernier message: 01/02/2005, 09h55
  5. [FLASH MX 2004] Affichage texte dynamique
    Par Sun3clipse dans le forum Flash
    Réponses: 8
    Dernier message: 25/06/2004, 16h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo