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

Python Discussion :

progressbar avec threading


Sujet :

Python

  1. #1
    Membre du Club
    Homme Profil pro
    ngénieur d'etat en science géodésique et travaux topographique
    Inscrit en
    Septembre 2016
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : ngénieur d'etat en science géodésique et travaux topographique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Septembre 2016
    Messages : 152
    Points : 65
    Points
    65
    Par défaut progressbar avec threading
    Bonjour;
    J'utilise une fonction qui prend un certain temps à s'exécuter. Je veux une progressbar qui suit les processus de cette fonction. C'est donc lorsque le processus est terminé le progressbar prend la valeur maximale de 100%.
    Si possible, un simple exemple qui est expliquant cette problématique parce que je l’ai déjà vu plusieurs exemples sur internt et je ne pas comprends puisque c'est la première fois que j'ai utlise threading avec pyqt5.

  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,

    Qu'est ce que vous ne comprenez pas dans un exemple simple trouvé sur Internet?
    note: on fera difficilement "mieux" que ce que vous avez déjà trouvé... et si vous ne détaillez pas ce que vous ne comprenez pas "répéter" n'aidera pas plus.

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

  3. #3
    Membre du Club
    Homme Profil pro
    ngénieur d'etat en science géodésique et travaux topographique
    Inscrit en
    Septembre 2016
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : ngénieur d'etat en science géodésique et travaux topographique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Septembre 2016
    Messages : 152
    Points : 65
    Points
    65
    Par défaut
    Merci wiztricks pour votre réponse
    mais dans cette exmple progressbar seulement sans processing de founction en parallèle

  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 rabeh.ram Voir le message
    mais dans cette exmple progressbar seulement sans processing de founction en parallèle
    Un thread qui met à jour la progressbar et, comme c'est un exemple, son travail se résume à time.sleep(0.3).

    Si vous voulez autre chose, il faudra être plus précis.

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

  5. #5
    Membre du Club
    Homme Profil pro
    ngénieur d'etat en science géodésique et travaux topographique
    Inscrit en
    Septembre 2016
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : ngénieur d'etat en science géodésique et travaux topographique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Septembre 2016
    Messages : 152
    Points : 65
    Points
    65
    Par défaut
    Citation Envoyé par wiztricks Voir le message

    Si vous voulez autre chose, il faudra être plus précis.

    - W
    ci-joint mon script avec form design je veux changer la valeur de progressbar en parallèle avec la fonction de calcul de proximité c'est a dire le temps que le calcul dans 20 % le progressbar affiche la valeur 20% et quand l'opération de calcul terminé le progressbar affiche 100%
    Fichiers attachés Fichiers attaché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 rabeh.ram Voir le message
    ci-joint mon script avec form design je veux changer la valeur de progressbar en parallèle avec la fonction de calcul de proximité
    Il n'y a pas de thread dans ce code là: impossible de savoir le problème rencontré...

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

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par rabeh.ram Voir le message
    ci-joint mon script avec form design je veux changer la valeur de progressbar en parallèle avec la fonction de calcul de proximité c'est a dire le temps que le calcul dans 20 % le progressbar affiche la valeur 20% et quand l'opération de calcul terminé le progressbar affiche 100%
    Un progressbar permet d'afficher une boucle de travail. Si par exemple j'ai besoin de tourner 50 fois un truc pour y arriver, je peux inclure dans ma boucle une mise à jour du progressbar qui va alors montrer la boucle progresser.
    Ta fonction find_proximity n'a pas cette boucle. Elle commence par récupérér tous les points (ok là il y a une boucle) puis fait sa recherche via np.sort() et df2.drop_duplicates() et la recherche est finie. Ok il est probable que ces méthodes ont des boucles interne mais tu n'y a pas accès.

    Eventuellement tu peux mettre à jour la progressbar dans la boucle de récupération (et peut-être aussi dans la boucle qui remplit la liste) mais ça s'arrête là.
    Et pas besoin de thread pour ça. Suffit que dans lesdites boucles tu fasses un update de la progressbar.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Membre du Club
    Homme Profil pro
    ngénieur d'etat en science géodésique et travaux topographique
    Inscrit en
    Septembre 2016
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : ngénieur d'etat en science géodésique et travaux topographique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Septembre 2016
    Messages : 152
    Points : 65
    Points
    65
    Par défaut
    Bonjour;
    merci wiztricks,Sve@r ; dans ce code et avec un grande data ( large Myfile.txt) j'ai remarqué que Le premier boucle et le partie de code qui est prend du temps ;
    c'est possible de lier le progressbar avec cette boucle

  9. #9
    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 rabeh.ram Voir le message
    c'est possible de lier le progressbar avec cette boucle
    Pour pouvoir relier cela à une progressbar, il faudrait déjà (savoir) calculer/estimer le pourcentage de ce qui a été fait (ou reste à faire)...

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

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par rabeh.ram Voir le message
    c'est possible de lier le progressbar avec cette boucle
    Faut voir si on peut obtenir le nombre de lignes à traiter avant de partir sur df.iterrows().
    Ensuite dans la boucle on met à jour la progressbar via une 4° de proportionnelle par rapport au nombre de lignes et à la valeur maximale de la progressbar (valeur à envoyer à la progress = n° ligne en cours * vMaxProgressBar / nb_lignes_total)
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  11. #11
    Membre du Club
    Homme Profil pro
    ngénieur d'etat en science géodésique et travaux topographique
    Inscrit en
    Septembre 2016
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : ngénieur d'etat en science géodésique et travaux topographique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Septembre 2016
    Messages : 152
    Points : 65
    Points
    65
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    (ou reste à faire)...

    - W
    oui il reste à faire; s'il vous plaît aidez-moi pour résoudre cette partie parce que jamais eu de problèmes comme ça.

  12. #12
    Membre du Club
    Homme Profil pro
    ngénieur d'etat en science géodésique et travaux topographique
    Inscrit en
    Septembre 2016
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : ngénieur d'etat en science géodésique et travaux topographique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Septembre 2016
    Messages : 152
    Points : 65
    Points
    65
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    (valeur à envoyer à la progress = n° ligne en cours * vMaxProgressBar / nb_lignes_total)
    Je vous ai compris, mais le partie qui est reste ce est le processus de mise a jour l'affichage de ProgressBar au meme temps de calcul puisque cette opération ne faite pas que avec Qthread et c’est la partie que je ne connais pas (Qthreading)

  13. #13
    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 rabeh.ram Voir le message
    c’est la partie que je ne connais pas (Qthreading)
    Ce qui vous ramène à la question de départ: ouvrir un tuto et comprendre comment çà fonctionne...

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

  14. #14
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par rabeh.ram Voir le message
    ne faite pas que avec Qthread et c’est la partie que je ne connais pas (Qthreading)
    Absolument pas. QThread n'est pas nécessaire pour mettre à jour une barre de progression lors d'un travail
    Code python : 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
    #!/usr/bin/env python3
    # coding: utf-8
     
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    from PyQt5.QtWidgets import *
    import sys
    import time
     
    class myWindow(QDialog):
    	def __init__(self, *args, **kwargs):
    		super().__init__(*args, **kwargs)
     
    		self.progressbar = QProgressBar(parent=self)
    		self.progressbar.setMaximum(150)
     
    		self.button = QPushButton("Start Progressbar", parent=self)
    		self.button.clicked[bool].connect(self.__slotProgressStart)
     
    		mainLayout = QVBoxLayout(self)
    		mainLayout.addWidget(self.progressbar)
    		mainLayout.addWidget(self.button)
    		self.show()
    	# __init__()
     
            @pyqtSlot(bool)
    	def __slotProgressStart(self):
    		for cnt in range(1, 101):
    			self.progressbar.setValue(cnt * self.progressbar.maximum() / 100)
    			time.sleep(0.1)
    		# for
    	# __slotProgressStart
    # class myWindow()
     
    App = QApplication(sys.argv)
    window = myWindow()
    sys.exit(App.exec())
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  15. #15
    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 Sve@r Voir le message
    Absolument pas. QThread n'est pas nécessaire pour mettre à jour une barre de progression lors d'un travail

    Bien que le PO s'attende a ce qu'on lui écrive le code quelque soit la solution... c'est quand même le sujet de la discussion?

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

  16. #16
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    c'est quand même le sujet de la discussion?
    Certes certes. Toutefois je pense qu'il s'est focalisé dessus alors qu'en réalité il n'en a pas vraiment besoin.

    Citation Envoyé par wiztricks Voir le message
    Bien que le PO s'attende a ce qu'on lui écrive le code...
    Tu as déjà donné un lien montrant un exemple très explicite (c'est d'ailleurs de là que j'ai écrit celui que j'ai posté tout à l'heure).
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  17. #17
    Membre du Club
    Homme Profil pro
    ngénieur d'etat en science géodésique et travaux topographique
    Inscrit en
    Septembre 2016
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : ngénieur d'etat en science géodésique et travaux topographique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Septembre 2016
    Messages : 152
    Points : 65
    Points
    65
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Absolument pas. QThread n'est pas nécessaire pour mettre à jour une barre de progression lors d'un travail
    j'ai essayé de lancer la barre de progression sans QThread comme c'est dans votre code mais le problème c'est que la barre de progression bloquée a valeur 0 pendant le traitement et avoir le max valeur après la fin de traitement (la barre de progression n'affiche pas le début de traitement)

  18. #18
    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 rabeh.ram Voir le message
    j'ai essayé de lancer la barre de progression sans QThread comme c'est dans votre code mais le problème c'est que la barre de progression bloquée a valeur 0 pendant le traitement et avoir le max valeur après la fin de traitement (la barre de progression n'affiche pas le début de traitement)
    Quelque part, c'est parce que vous vous y êtes "mal pris"... mais sans montrer ce que vous avez essayé, difficile de savoir ce que vous n'avez pas compris...

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

  19. #19
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Salut,

    Les opérations exécutées dans un thread (autre que le main) doivent utiliser les signaux pour communiquer avec l'interface.

    Un exemple simple qui télécharge un petit fichier (sur arte Concert) et met à jour les widgets de progression.
    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
     
    import os
    import sys
    import contextlib
    import urllib.request
    import time
    from threading import Thread
     
    from PyQt5.QtCore import pyqtSignal, QLocale
    from PyQt5.QtWidgets import (QApplication, QMainWindow, QGridLayout, QVBoxLayout, 
                                 QWidget, QLabel, QProgressBar)
     
    class Main(QMainWindow):
        loadingProgress = pyqtSignal(int, int, int)
        loadingFinished = pyqtSignal()
        def __init__(self):
            super().__init__()
            self.resize(394, 176)
            self.centralwidget = QWidget(self)
            self.gLayout = QGridLayout(self.centralwidget)
            self.vLayout = QVBoxLayout()
            self.label = QLabel(self.centralwidget)
            self.label.setText("Téléchargement en cours")
            self.vLayout.addWidget(self.label)
            self.progressBar = QProgressBar(self.centralwidget)
            self.progressBar.setRange(0, 100)
            self.vLayout.addWidget(self.progressBar)
            self.speed_lbl = QLabel(self.centralwidget)
            self.speed_lbl.setText("Bande passante: ")
            self.vLayout.addWidget(self.speed_lbl)
            self.remain_lbl = QLabel(self.centralwidget)
            self.remain_lbl.setText("Temp restant: ")
            self.vLayout.addWidget(self.remain_lbl)
            self.gLayout.addLayout(self.vLayout, 0, 0, 1, 1)
            self.setCentralWidget(self.centralwidget)
            lang = QLocale.system().name()
            self.locale = QLocale(lang)
            # Tout se passe ici
            self.loadingProgress.connect(self.on_progress)
            self.loadingFinished.connect(self.on_finished)
     
        def active(self):
            # Téléchargeons un petit fichier +- 120 Mo
            url = "https://arteconcert-a.akamaihd.net/am/concert/103000/103900/"\
                  "103922-004-A_SQ_0_VOF_05966404_MP4-2200_AMM-CONCERT-NEXT_"\
                  "1aOw2lrIj0.mp4"
            target = os.path.join(os.getcwd(), "Ballaké Sissoko.mp4")
            Thread(target=self.download, args=(url, target)).start()
     
        def download(self, url, filename):
            size = 0
            try:
                with contextlib.closing(urllib.request.urlopen(url, None, 6)) as fp:
                    bs = 1024 * 16
                    percent = 1
                    blocknum = 0
                    amount = 0
                    blocks_percent = 0
                    headers = fp.info()
                    if "content-length" in headers:
                        size = int(headers["Content-Length"])
                        blocks_percent = int(size / bs / 100)
     
                    begin_at = time.time()
                    with open(filename, 'wb') as target:
                        while True:
                            block = fp.read(bs)
                            if not block:
                                break
     
                            target.write(block)
                            blocknum += 1
                            amount += bs
                            if blocknum == blocks_percent:
                                elapsed = time.time() - begin_at
                                speed = int(amount / elapsed)
                                remain = int(size - amount)
                                self.loadingProgress.emit(percent, speed, remain)
                                percent += 1
                                blocknum = 0
            except URLError as why:
                print("Download error: %s" % why)
     
            self.loadingFinished.emit()
     
        def on_progress(self, percent, speed, remain):
            # Ici nous sommes dans le thread principal, aucun danger pour le serveur
            # graphique.
            rtime = int(remain / speed)
            speed = self.locale.toString(int(speed / 1024))
            self.progressBar.setValue(percent)
            self.speed_lbl.setText("Bande passante: %s Kio/sec." % speed)
            m, s = divmod(rtime, 60)
            self.remain_lbl.setText("Temp restant: %s min. %s sec." %(m, s))
     
        def on_finished(self):
            self.label.setText("Téléchargement terminé.")
     
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        main = Main()
        main.show()
        main.active()
        sys.exit(app.exec_())
    C'est rapide mais la progression est fluide.

  20. #20
    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 réponds ici à une question posée par mp.

    La mise en place d'une barre de progression pour informer l'utilisateur de la progression d'une opération longue est facile, et répond à plusieurs exigences logiques quand on travaille sur un programme graphique (PyQt5 ici):

    - une opération longue (calcul, téléchargement FTP, etc...) est forcément exécutée de façon asynchrone (thread, processus) par rapport au graphique. La raison est simple à comprendre: si ce n'est pas le cas, pendant que le CPU s'occupe de l'opération longue, il ne s'occupe pas du graphique qui est donc "figé" et n'écoute pas les demandes type souris, clavier, ...

    - pour qu'une opération longue puisse mettre à jour le graphique, il faut qu'elle puisse donner une information de progression pendant le déroulement de cette opération, et, bien sûr, en connaître dès le début la quantité totale (celle qui fera 100%). Ce n'est pas toujours évident à faire, et nécessite quelquefois une reprogrammation de l'opération longue. Par exemple, pour copier un grand fichier, on peut coder la recopie par bloc (et compter les blocs copiés) au lieu d'utiliser copy2 de shutil. A défaut, il y a toujours la possibilité de mettre la barre de progression sous forme de "chenille" pour informer seulement l'utilisateur qu'une opération longue est en cours. On peut aussi mettre en place un "throbber" (une petite roue qui tourne) au lieu d'une barre.

    - l'opération asynchrone ne doit pas toucher directement au graphique (sinon, plantage aléatoire). La mise à jour de la barre de progression est faite par l'envoi de l'information de progression sous forme d'un message envoyé par le thread ".emit(...)". L'envoi de ce message déclenche l'exécution d'une méthode du graphique pour la mise à jour. A noter que pour que le thread puisse envoyer un message, il faut qu'il soit sous-classé par QThread, ou sinon par un héritage multiple de threading + QObject.

    - Selon l'opération longue en question, le choix du thread peut ne pas être la meilleure solution si on veut que les calculs soient faits en parallèle. On peut, dans ce cas, faire que le thread lance lui-même le calcul par multiprocessing utilisant tous les cœurs disponibles du CPU. Je peux fournir un code si nécessaire.

    Voilà un petit exemple tout simple et largement documenté utilisant QThread:

    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
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    # -*- coding: utf-8 -*-
     
    import sys
    import time
    from PyQt5 import (QtWidgets, QtCore)
     
    #############################################################################
    class Operationlongue(QtCore.QThread):
     
        # crée deux nouveaux signaux pour communiquer avec le graphique
        info = QtCore.pyqtSignal(int) # signal pour informer d'une progression
        fini = QtCore.pyqtSignal(bool, list) # signal pour informer de la fin du thread
     
        #========================================================================
        def __init__(self, parent=None):
            super().__init__(parent)
     
            # initialise un drapeau pour signaler une demande d'arrêt anticipé
            self.stop = False 
     
        #========================================================================
        def run(self):
            """seule partie qui s'exécute en tâche de fond
            """
            for i in range(0, 101):
                if self.stop:
                    break # arrêt anticipé demandé
                time.sleep(0.05) # tempo pour ralentir la boucle
                self.info.emit(i) # envoi du signal de progression d'exécution
     
            # envoi du signal de fin du thread:
            #   self.stop dira si la fin est normale (False) ou pas (True)
            #   et [1,2,3] n'est qu'un exemple de données envoyées par le thread
            self.fini.emit(self.stop, [1,2,3]) 
     
        #========================================================================
        def arreter(self):
            """pour arrêter avant la fin normale d'exécution du thread
            """
            self.stop = True
     
    #############################################################################
    class Fenetre(QtWidgets.QWidget):
     
        #========================================================================
        def __init__(self, parent=None):
            super().__init__(parent)
     
            # bouton de lancement du thread
            self.depart = QtWidgets.QPushButton("Départ", self)
            self.depart.clicked.connect(self.lancement)
     
            # bouton d'arrêt anticipé du thread
            self.arret = QtWidgets.QPushButton("Arrêt", self)
            self.arret.clicked.connect(self.stopthread)
     
            # barre de progression
            self.pbarre = QtWidgets.QProgressBar(self)
            self.pbarre.setAlignment(QtCore.Qt.AlignHCenter)
     
            self.pbarre.setRange(0, 100)
            self.pbarre.setValue(0)
     
            # positionne les widgets dans la fenêtre
            posit = QtWidgets.QGridLayout()
            posit.addWidget(self.depart, 0, 0)
            posit.addWidget(self.arret, 1, 0)
            posit.addWidget(self.pbarre, 2, 0)
            self.setLayout(posit)
     
            # initialise la variable d'instance de classe du thread
            self.operationlongue = None
     
        #========================================================================
        @QtCore.pyqtSlot(bool)
        def lancement(self, ok=False):
            """lance l'opération longue dans le thread
            """
            if self.operationlongue==None or not self.operationlongue.isRunning():
                # initialise la barre de progression
                self.pbarre.reset()
                self.pbarre.setRange(0, 100)
                self.pbarre.setValue(0)
                # initialise l'opération longue dans le thread
                self.operationlongue = Operationlongue()
                # prépare la réception du signal de progression
                self.operationlongue.info.connect(self.progression)
                # prépare la réception du signal de fin
                self.operationlongue.fini.connect(self.finduthread)
                # lance le thread (mais ne l'attend pas avec .join!!!)
                self.operationlongue.start()
     
        #========================================================================
        @QtCore.pyqtSlot(int)
        def progression(self, i):
            """lancé à chaque réception d'info de progression émise par le thread
            """
            self.pbarre.setValue(i)
     
        #========================================================================
        @QtCore.pyqtSlot(bool)
        def stopthread(self, ok=False):
            """pour arrêter avant la fin
            """
            if self.operationlongue!=None and self.operationlongue.isRunning():
                self.operationlongue.arreter()
     
        #========================================================================
        @QtCore.pyqtSlot(bool, list)
        def finduthread(self, fin_anormale=False, liste=()):
            """Lancé quand le thread se termine
            """
            if fin_anormale:
                # fin anticipée demandée
                QtWidgets.QMessageBox.information(self,
                    "Opération longue",
                    "Arrêt demandé avant la fin!")
            else:
                # fin normale
                self.pbarre.setValue(100)
                QtWidgets.QMessageBox.information(self,
                    "Opération longue",
                    "Fin normale!")
                # récupération des infos transmises par signal à la fin du thread
                print("Infos données par le thread:", liste)
            # désactive les liens
            self.operationlongue.info.disconnect()
            self.operationlongue.fini.disconnect() 
            # signale quil n'y a plus de thread actif
            self.operationlongue = None
     
        #========================================================================
        def closeEvent(self, event):
            """lancé à la fermeture de la fenêtre quelqu'en soit la méthode
            """
            # si le thread est en cours d'eécution, on l'arrête (brutalement!)
            if self.operationlongue!=None and self.operationlongue.isRunning():
                # désactive les liens
                self.operationlongue.info.disconnect()
                self.operationlongue.fini.disconnect()                        
                # et arrête brutalement le thread
                self.operationlongue.terminate()
            # accepte la fermeture de la fenêtre
            event.accept()
     
    #############################################################################
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        fen = Fenetre()
        fen.show()
        sys.exit(app.exec_())
    [edit] petite correction du code: remplacement de connect par disconnect() aux lignes 128 et 140
    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

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [PB] Progressbar avec thread
    Par todier dans le forum C#
    Réponses: 3
    Dernier message: 15/06/2007, 10h46
  2. [SWING] Exception bizarre avec Thread
    Par Gob4 dans le forum Débuter
    Réponses: 2
    Dernier message: 13/09/2005, 21h55
  3. [MFC] Cherche Timer avec thread
    Par romeo9423 dans le forum MFC
    Réponses: 17
    Dernier message: 09/03/2005, 10h33
  4. Variable static avec thread
    Par oxor3 dans le forum Threads & Processus
    Réponses: 7
    Dernier message: 27/08/2004, 11h45
  5. ProgressBar avec plusieurs procédures
    Par elifqaoui dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 08/09/2002, 18h03

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