In the previous introduction, as the name suggests, we explained about Kivy, built the environment, and executed the sample program. This time, I would like to introduce the progress bar when doing something. It seems to be a little niche article that feels like a title scam, but please forgive me. I think that the article will be like this from the next time w
As you all know, [wikipedia](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%AC%E3 % 82% B9% E3% 83% 90% E3% 83% BC) I will quote the outline.
The progress bar (English: Progress Bar) is one of the elements (widgets) of the graphical user interface, which visually and intuitively displays how much the progress of a task that takes a long time has been completed. .. Often used when displayed in percentage format, such as downloads and file transfers. Also known as Progress Meters.
It's such a guy. (This image is also [wikipedia](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%AC%E3%82% From B9% E3% 83% 90% E3% 83% BC))
When I implemented some time-consuming behavior in kivy, I wanted a progress bar, Kivy Reference has almost no explanation. I ended up wandering around the net. .. ..
It works like this.
The source is as follows.
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)
#Progress bar widget
self.pb = ProgressBar()
self.add_widget(self.pb)
#Process start button widget
button_pb = Button(text='progress')
#Associate processing with a button
button_pb.bind(on_press=self.test_progress)
self.add_widget(button_pb)
#Repeat the process at regular intervals
def pb_clock(self,dt):
#Stops the clock when the progress bar reaches its maximum value
if self.pb.value == 100:
return False
#Increase the value of the progress bar
self.pb.value += 1
def test_progress(self, *args):
self.pb.value = 0
#Clock start
Clock.schedule_interval(self.pb_clock, 1/60)
class TestProgress(App):
def build(self):
return ProgressTest()
if __name__ == '__main__':
TestProgress().run()
The important thing is the processing of Clock. Even if the value of the progress bar is updated with the for statement or the value of the value itself is updated, the progress bar on the screen does not change until the for processing is completed. Therefore, we use Clock, which is called sequentially every time of kivy and draws the screen.
I wrote the above source as a usage, but considering that the progress bar is actually used, I feel that it is often embedded in a pop-up or something.
Also, in the above program, it is necessary to write the process you want to perform in the Clock process, In order to visualize the progress of iterative processing of the existing class, I think that the for statement needs to be rewritten for Clock.
Therefore, we will further customize it so that the progress of processing from the external class can be visualized on the pop-up.
This time, I would like to implement a process to operate two progress bars at the same time on the popup. The image looks like the figure below.
A function of another class is used as a sub process, and the main process is completed after each sub process. It is assumed that the progress bar will advance.
As mentioned in the usage chapter, if you perform a slightly longer process of the for statement in another class, the screen will become dark and the operation will not work. Official also has a description like this.
When I try to move the second program bar, even if the process itself is working, screen drawing is not accepted, and I can not tell if it is working only with the GUI.
Therefore, in order to force the screen to be drawn, the threading module of Python is used so that the screen can be drawn while processing. (I don't know if it's a straightforward approach, but it works fine.)
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
#Class assuming heavy processing
from NagaiSyori import longProc
class ProgressPop(BoxLayout):
def __init__(self, **kwargs):
super(ProgressPop, self).__init__(**kwargs)
#Button to bring up a pop-up
button_pb = Button(text='thread pop!!')
button_pb.bind(on_press=self.open_pupup)
self.add_widget(button_pb)
#self.tmp = 0
#Class that does heavy external processing
self.sub_process = longProc()
#Flag to end thread processing
self.thread_flag = False
#Pop-up screen and its processing
def open_pupup(self, btn):
#Pop-up screen base
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)
#Pop-up widget
self._pup = Popup(title="Popup Test",
content=content,
size_hint=(0.5,0.5))
#Open a pop-up
self._pup.open()
#Preparing for thread processing
self.thread_flag = True
self.ev = threading.Event()
#Thread processing started
self.thed = threading.Thread(target=self.test_progress)
self.thed.start()
#Processing when closing the pop-up
def dissmiss(self, *args):
self.ev.clear()
self.thread_flag = False
self._pup.dismiss()
#Updated the value of the main progress bar
def main_clock(self, *args):
#Stops the clock when the progress bar value reaches its maximum
if self.tmp >= 100:
Clock.unschedule(self.main_clock)
self.pb.value = self.tmp
#Update the value of the sub progress bar
def sub_clock(self, *args):
#Stops the clock when the progress bar value reaches its maximum
if self.sub_process.num >= 100:
Clock.unschedule(self.sub_clock)
self.sub_pb.value = self.sub_process.num
#processing
def test_progress(self):
#Variables for passing values to the progress bar
self.tmp = 0
#Clock start to update the value to the progress bar
Clock.schedule_interval(self.main_clock, 1 / 60)
for i in range(20):
#If all the processing is not finished
if self.thread_flag:
time.sleep(1/60)
#Clock to update the value of the sub progress bar
Clock.schedule_interval(self.sub_clock, 1 / 60)
#Heavy processing
self.sub_process.process()
self.tmp = i*5 + 5
print(self.tmp)
#Thread termination processing when all processing is completed
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 for passing values to the progress bar
self.num = 0
#Heavy processing
def process(self):
self.num = 0
for i in range(100):
time.sleep(1/600)
self.num = i + 1
If you execute it, it will work like this.
By adding thread processing, it is not necessary to write repetitive processing in Clock. In addition, it is now possible to visualize the processing status of external classes! !! !!
It was very helpful. thank you very much.
Progress bar in pop-up with Python Kivy
Python | Progress Bar widget in kivy - GeeksforGeeks
Recommended Posts