[PYTHON] Programmation GUI utilisant kivy ~ Partie 2 Barre de progression ~

introduction

Dans l'introduction précédente, comme son nom l'indique, nous avons expliqué Kivy, construit l'environnement et exécuté l'exemple de programme. Cette fois, je voudrais présenter la barre de progression lorsque je fais quelque chose. Cela semble être un article légèrement de niche qui ressemble à une arnaque de titre, mais pardonnez-moi s'il vous plaît. Je pense que l'article sera comme ça à partir de la prochaine fois w

Qu'est-ce qu'une barre de progression?

Comme vous le savez tous, [wikipedia](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%AC%E3 Je vais citer le schéma de% 82% B9% E3% 83% 90% E3% 83% BC).

La barre de progression (en anglais: Barre de progression) est l'un des éléments (widgets) de l'interface utilisateur graphique qui affiche visuellement et intuitivement à quel point la progression d'une tâche qui prend du temps a été accomplie. .. Souvent utilisé lorsqu'il est affiché au format pourcentage, comme les téléchargements et les transferts de fichiers. Aussi connu sous le nom de Progress Mètres.

C'est un tel gars. (Cette image est également [wikipedia](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%AC%E3%82% À partir de B9% E3% 83% 90% E3% 83% BC))

Quand j'ai implémenté un comportement chronophage dans kivy, je voulais une barre de progression, Référence Kivy n'a presque aucune explication. J'ai fini par errer sur le filet. .. ..

Comment utiliser la barre de progression avec kivy

Cela fonctionne comme ça.

pb1.gif

La source est la suivante.

from kivy.app import App
from kivy.clock import Clock
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.progressbar import ProgressBar

class ProgressTest(BoxLayout):
    def __init__(self, **kwargs):
        super(ProgressTest, self).__init__(**kwargs)
        #Widget de la barre de progression
        self.pb = ProgressBar()
        self.add_widget(self.pb)
        
        #Lancer le widget du bouton de traitement
        button_pb = Button(text='progress')
        #Associer le traitement à un bouton
        button_pb.bind(on_press=self.test_progress)
        self.add_widget(button_pb)

    #Répétez le processus à intervalles réguliers
    def pb_clock(self,dt):
        #Arrête l'horloge lorsque la barre de progression atteint sa valeur maximale
        if self.pb.value == 100:
            return False
        #Augmenter la valeur de la barre de progression
        self.pb.value += 1

    def test_progress(self, *args):
        self.pb.value = 0
        #Début de l'horloge
        Clock.schedule_interval(self.pb_clock, 1/60)

class TestProgress(App):
    def build(self):
        return ProgressTest()


if __name__ == '__main__':
    TestProgress().run()

L'important est le traitement de Clock. Même si la valeur de la barre de progression est mise à jour avec l'instruction for ou si la valeur de la valeur elle-même est mise à jour, la barre de progression à l'écran ne change pas tant que le traitement n'est pas terminé. Par conséquent, nous utilisons Clock, qui est appelée séquentiellement à chaque fois de kivy et dessine l'écran.

J'ai écrit la source ci-dessus comme une utilisation, mais étant donné que la barre de progression est réellement utilisée, j'ai l'impression qu'elle est souvent incorporée dans une fenêtre contextuelle ou quelque chose comme ça.

En outre, dans le programme ci-dessus, il est nécessaire d'écrire le processus que vous souhaitez effectuer dans le processus d'horloge, Pour visualiser la progression du traitement itératif des classes existantes, je pense que l'instruction for doit être réécrite pour Clock.

Par conséquent, nous allons le personnaliser afin que la progression du traitement de la classe externe puisse être visualisée sur la fenêtre contextuelle.

Ce que tu veux faire

Cette fois, je voudrais implémenter un processus pour faire fonctionner deux barres de progression en même temps sur le pop-up. L'image ressemble à la figure ci-dessous.

イメージ.png

Une fonction d'une autre classe est utilisée comme sous-processus, et le processus principal est terminé après chaque sous-processus. On suppose que la barre de progression avancera.

Comme mentionné dans le chapitre d'utilisation, si vous effectuez un processus légèrement plus long de l'instruction for dans une autre classe, l'écran deviendra sombre et l'opération ne fonctionnera pas. Officiel a également une description comme celle-ci.

Lorsque j'essaye de déplacer la deuxième barre sans programme, même si le processus lui-même fonctionne, le dessin d'écran n'est pas accepté et je ne peux pas dire s'il fonctionne uniquement avec l'interface graphique.

Par conséquent, afin de forcer l'écran à être dessiné, le module de threading de Python est utilisé afin que l'écran puisse être dessiné pendant le traitement. (Je ne sais pas si c'est une approche simple, mais cela fonctionne bien.)

Code source

sample.py


from kivy.uix.progressbar import ProgressBar
from kivy.uix.popup import Popup
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button

import time
import threading

#Classe supposant un traitement lourd
from NagaiSyori import longProc


class ProgressPop(BoxLayout):
    def __init__(self, **kwargs):
        super(ProgressPop, self).__init__(**kwargs)
        #Bouton pour faire apparaître une fenêtre contextuelle
        button_pb = Button(text='thread pop!!')
        button_pb.bind(on_press=self.open_pupup)
        self.add_widget(button_pb)
        #self.tmp = 0
        #Classe qui effectue un traitement externe lourd
        self.sub_process = longProc()
        #Indicateur pour terminer le traitement des threads
        self.thread_flag = False

    #Écran contextuel et son traitement
    def open_pupup(self, btn):
        #Base d'écran pop-up
        content = BoxLayout(orientation='vertical')
        self.pb = ProgressBar()
        content.add_widget(self.pb)
        self.sub_pb= ProgressBar()
        content.add_widget(self.sub_pb)
        self._close = Button(text="close",
                             on_press=self.dissmiss)
        content.add_widget(self._close)
        #Widget contextuel
        self._pup = Popup(title="Popup Test",
                          content=content,
                          size_hint=(0.5,0.5))
        #Ouvrez une fenêtre contextuelle
        self._pup.open()

        #Préparation au traitement des threads
        self.thread_flag = True
        self.ev = threading.Event()

        #Démarrer le traitement des threads
        self.thed = threading.Thread(target=self.test_progress)
        self.thed.start()

    #Traitement lors de la fermeture du pop-up
    def dissmiss(self, *args):
        self.ev.clear()
        self.thread_flag = False
        self._pup.dismiss()

    #Mise à jour de la valeur de la barre de progression principale
    def main_clock(self, *args):
        #Arrêtez l'horloge lorsque la valeur de la barre de progression atteint son maximum
        if self.tmp >= 100:
            Clock.unschedule(self.main_clock)
        self.pb.value = self.tmp

    #Mettre à jour la valeur de la barre de progression secondaire
    def sub_clock(self, *args):
        #Arrêtez l'horloge lorsque la valeur de la barre de progression atteint son maximum
        if self.sub_process.num >= 100:
            Clock.unschedule(self.sub_clock)
        self.sub_pb.value = self.sub_process.num

    #En traitement
    def test_progress(self):
        #Variables pour transmettre des valeurs à la barre de progression
        self.tmp = 0
        #L'horloge commence à mettre à jour la valeur de la barre de progression
        Clock.schedule_interval(self.main_clock, 1 / 60)
        for i in range(20):
            #Si tout le traitement n'est pas terminé
            if self.thread_flag:
                time.sleep(1/60)
                #Horloge pour mettre à jour la valeur de la barre de progression secondaire
                Clock.schedule_interval(self.sub_clock, 1 / 60)
                #Traitement lourd
                self.sub_process.process()
                self.tmp = i*5 + 5
                print(self.tmp)
        #Traitement de fin de thread lorsque tout le traitement est terminé
        self.ev.clear()
        self.thread_flag = False

class TestPopupProgressApp(App):
    def build(self):
        return ProgressPop()


if __name__ == '__main__':
    TestPopupProgressApp().run()

NagaiSyori.py


import time
class longProc:
    def __init__(self):
        #Variables pour transmettre des valeurs à la barre de progression
        self.num = 0

    #Traitement lourd
    def process(self):
        self.num = 0
        for i in range(100):
            time.sleep(1/600)
            self.num = i + 1

pb2.gif

Si vous l'exécutez, cela fonctionnera comme ceci.

En ajoutant un traitement de thread, il n'est pas nécessaire d'écrire un traitement répétitif dans Clock. De plus, il est désormais possible de visualiser l'état de traitement des classes externes! !! !!

Article de référence

Cela a été très utile. Merci beaucoup.

Barre de progression dans une fenêtre contextuelle avec Python Kivy

Python | Progress Bar widget in kivy - GeeksforGeeks

Recommended Posts

Programmation GUI utilisant kivy ~ Partie 2 Barre de progression ~
Programmation GUI avec kivy ~ Partie 6 Diverses dispositions ~
Programmation GUI avec kivy ~ Partie 3 Vidéo et barre de recherche ~
Programmation GUI à l'aide de kivy ~ Partie 5 Création de boutons avec des images ~
Programmation GUI en Python avec Appjar
[Python] Affichage de la progression par barre de progression en utilisant tqdm