[PYTHON] GUI-Programmierung mit kivy ~ Teil 2 Fortschrittsbalken ~

Einführung

In der vorherigen Einführung haben wir, wie der Name schon sagt, Kivy erklärt, die Umgebung erstellt und das Beispielprogramm ausgeführt. Dieses Mal möchte ich den Fortschrittsbalken einführen, wenn ich etwas tue. Es scheint ein Nischenartikel zu sein, der sich wie ein Titelbetrug anfühlt, aber bitte verzeihen Sie mir. Ich denke, dass der Artikel ab dem nächsten Mal so sein wird w

Was ist ein Fortschrittsbalken?

Wie Sie alle wissen, [wikipedia](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%AC%E3 Ich zitiere die Gliederung aus% 82% B9% E3% 83% 90% E3% 83% BC).

Der Fortschrittsbalken (Englisch: Fortschrittsbalken) ist eines der Elemente (Widgets) der grafischen Benutzeroberfläche, die den Fortschritt einer Aufgabe, die lange dauert, visuell und intuitiv anzeigen. .. Wird häufig verwendet, wenn es im Prozentformat angezeigt wird, z. B. Downloads und Dateiübertragungen. Auch als Fortschrittsmesser bekannt.

Es ist so ein Typ. (Dieses Bild ist auch [Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%AC%E3%82% Von B9% E3% 83% 90% E3% 83% BC))

Als ich ein zeitaufwändiges Verhalten in Kivy implementierte, wollte ich einen Fortschrittsbalken. Kivy Reference hat fast keine Erklärung. Am Ende bin ich durch das Netz gewandert. .. ..

Verwendung des Fortschrittsbalkens mit kivy

Es funktioniert so.

pb1.gif

Die Quelle ist wie folgt.

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)
        #Fortschrittsbalken-Widget
        self.pb = ProgressBar()
        self.add_widget(self.pb)
        
        #Starten Sie die Verarbeitung des Schaltflächen-Widgets
        button_pb = Button(text='progress')
        #Verknüpfen Sie die Verarbeitung mit einer Schaltfläche
        button_pb.bind(on_press=self.test_progress)
        self.add_widget(button_pb)

    #Wiederholen Sie den Vorgang in regelmäßigen Abständen
    def pb_clock(self,dt):
        #Stoppen Sie die Uhr, wenn der Fortschrittsbalken seinen Maximalwert erreicht
        if self.pb.value == 100:
            return False
        #Erhöhen Sie den Wert des Fortschrittsbalkens
        self.pb.value += 1

    def test_progress(self, *args):
        self.pb.value = 0
        #Uhr starten
        Clock.schedule_interval(self.pb_clock, 1/60)

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


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

Das Wichtigste ist die Verarbeitung der Uhr. Selbst wenn der Wert des Fortschrittsbalkens mit der for-Anweisung aktualisiert wird oder der Wert des Werts selbst aktualisiert wird, ändert sich der Fortschrittsbalken auf dem Bildschirm erst, wenn die Verarbeitung abgeschlossen ist. Daher verwenden wir Clock, die jedes Mal nacheinander von kivy aufgerufen wird und den Bildschirm zeichnet.

Ich habe die obige Quelle als Verwendung geschrieben, aber wenn man bedenkt, dass der Fortschrittsbalken tatsächlich verwendet wird, habe ich das Gefühl, dass er oft in einem Popup oder so etwas enthalten ist.

Im obigen Programm ist es außerdem erforderlich, den Prozess zu schreiben, den Sie im Clock-Prozess ausführen möchten. Um den Fortschritt der iterativen Verarbeitung vorhandener Klassen zu visualisieren, muss die for-Anweisung für Clock neu geschrieben werden.

Daher werden wir es so anpassen, dass der Fortschritt der Verarbeitung von der externen Klasse im Popup angezeigt werden kann.

Was du machen willst

Dieses Mal möchte ich einen Prozess implementieren, um zwei Fortschrittsbalken gleichzeitig im Popup zu bedienen. Das Bild sieht aus wie in der Abbildung unten.

イメージ.png

Eine Funktion einer anderen Klasse wird als Unterprozess verwendet, und der Hauptprozess wird nach jedem Unterprozess abgeschlossen. Es wird davon ausgegangen, dass der Fortschrittsbalken vorrückt.

Wie im Verwendungskapitel erwähnt, wird der Bildschirm dunkel und der Vorgang funktioniert nicht, wenn Sie einen etwas längeren Prozess der for-Anweisung in einer anderen Klasse ausführen. Official hat auch eine Beschreibung wie diese.

Wenn ich versuche, die zweite programmlose Leiste zu verschieben, wird das Zeichnen von Bildschirmen nicht akzeptiert, selbst wenn der Prozess selbst funktioniert, und ich kann nicht feststellen, ob es nur mit der GUI funktioniert.

Um das Zeichnen des Bildschirms zu erzwingen, wird das Threading-Modul von Python verwendet, um das Zeichnen des Bildschirms während der Verarbeitung durchzuführen. (Ich weiß nicht, ob es ein einfacher Ansatz ist, aber es funktioniert gut.)

Quellcode

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

#Klasse unter der Annahme einer starken Verarbeitung
from NagaiSyori import longProc


class ProgressPop(BoxLayout):
    def __init__(self, **kwargs):
        super(ProgressPop, self).__init__(**kwargs)
        #Schaltfläche zum Aufrufen eines Popups
        button_pb = Button(text='thread pop!!')
        button_pb.bind(on_press=self.open_pupup)
        self.add_widget(button_pb)
        #self.tmp = 0
        #Klasse, die schwere externe Verarbeitung ausführt
        self.sub_process = longProc()
        #Flag zum Beenden der Thread-Verarbeitung
        self.thread_flag = False

    #Popup-Bildschirm und seine Verarbeitung
    def open_pupup(self, btn):
        #Popup-Bildschirmbasis
        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)
        #Popup-Widget
        self._pup = Popup(title="Popup Test",
                          content=content,
                          size_hint=(0.5,0.5))
        #Öffnen Sie ein Popup
        self._pup.open()

        #Vorbereitung für die Thread-Verarbeitung
        self.thread_flag = True
        self.ev = threading.Event()

        #Starten Sie die Thread-Verarbeitung
        self.thed = threading.Thread(target=self.test_progress)
        self.thed.start()

    #Verarbeitung beim Schließen des Popups
    def dissmiss(self, *args):
        self.ev.clear()
        self.thread_flag = False
        self._pup.dismiss()

    #Der Wert des Hauptfortschrittsbalkens wurde aktualisiert
    def main_clock(self, *args):
        #Stoppen Sie die Uhr, wenn der Fortschrittsbalken maximal ist
        if self.tmp >= 100:
            Clock.unschedule(self.main_clock)
        self.pb.value = self.tmp

    #Aktualisieren Sie den Wert des Unterfortschrittsbalkens
    def sub_clock(self, *args):
        #Stoppen Sie die Uhr, wenn der Fortschrittsbalken maximal ist
        if self.sub_process.num >= 100:
            Clock.unschedule(self.sub_clock)
        self.sub_pb.value = self.sub_process.num

    #wird bearbeitet
    def test_progress(self):
        #Variablen zum Übergeben von Werten an den Fortschrittsbalken
        self.tmp = 0
        #Uhr starten, um den Wert auf den Fortschrittsbalken zu aktualisieren
        Clock.schedule_interval(self.main_clock, 1 / 60)
        for i in range(20):
            #Wenn die gesamte Verarbeitung nicht abgeschlossen ist
            if self.thread_flag:
                time.sleep(1/60)
                #Uhr, um den Wert des Unterfortschrittsbalkens zu aktualisieren
                Clock.schedule_interval(self.sub_clock, 1 / 60)
                #Schwere Verarbeitung
                self.sub_process.process()
                self.tmp = i*5 + 5
                print(self.tmp)
        #Thread-Beendigungsverarbeitung, wenn die gesamte Verarbeitung abgeschlossen ist
        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):
        #Variablen zum Übergeben von Werten an den Fortschrittsbalken
        self.num = 0

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

pb2.gif

Wenn Sie es ausführen, wird es so funktionieren.

Durch Hinzufügen der Thread-Verarbeitung ist es nicht erforderlich, die wiederholte Verarbeitung in Clock zu schreiben. Außerdem ist es jetzt möglich, den Verarbeitungsstatus externer Klassen zu visualisieren! !! !!

Referenzartikel

Es war sehr hilfreich. Vielen Dank.

Fortschrittsbalken im Popup mit Python Kivy

Python | Progress Bar widget in kivy - GeeksforGeeks

Recommended Posts

GUI-Programmierung mit kivy ~ Teil 2 Fortschrittsbalken ~
GUI-Programmierung mit kivy ~ Teil 6 Verschiedene Layouts ~
GUI-Programmierung mit kivy ~ Teil 3 Video und Suchleiste ~
GUI-Programmierung mit kivy ~ Teil 5 Erstellen von Schaltflächen mit Bildern ~
GUI-Programmierung in Python mit Appjar
[Python] Fortschrittsanzeige nach Fortschrittsbalken mit tqdm