I have a ProgressBar in my kivy app. I believe I need to use Clock.create_trigger
to ensure the progress bar updates from inside of a loop.
I've attempted to adapt the solutions from Progress bar in kivy can't update using loop and Kivy How can i create time counter with progressbar? for my solution, however, the bar still does not update until the very end.
The following code is a watered-down version for reproducibility purposes.
ProgressBar Class
from kivy.clock import Clock
from kivy.uix.progressbar import ProgressBar
class MyProgressBar(ProgressBar):
def __init__(self, *args, **kwargs):
super(MyProgressBar, self).__init__(*args, **kwargs)
# self.update_bar_trigger = Clock.create_trigger(self.update_bar)
self.update_bar_trigger = Clock.create_trigger(lambda dt: self.update_bar(), 1)
def update_bar(self, step):
if self.value <= 100:
self.value += step
self.update_bar_trigger()
Main class:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivy.properties import ObjectProperty
from MyProgressBar import MyProgressBar
from kivy.lang import Builder
Builder.load_file('style.kv')
class Main_app(BoxLayout):
# Progress bars
loading_pb = MyProgressBar()
def dummy(self):
pb_increment = 10
for i in range(10):
time.sleep(2)
self.loading_pb.update_bar(pb_increment)
print(self.loading_pb.value)
class Stacked(App):
def build(self):
Window.clearcolor = (1, 1, 1, 1)
Window.size = (1000, 700)
return Main_app()
if __name__ == '__main__':
Stacked().run()
KV File
<Main_app>:
loading_pb: load_pb
GridLayout:
rows: 2
MyProgressBar:
id: load_pb
value: 0
min: 0
max: 100
Button:
text: 'Start Progress Bar'
on_press:
root.dummy()
This example shows loading_pb.value changing as the code loops through after the button is clicked.
ProgressBar.value printed output
10.0
20.0
30.0
40.0
50.0
60.0
70.0
80.0
90.0
100.0
Problem The progress bar value does seem to increment as expected, but the actual progress bar does not change until all at once, at the end of the loop.
Related
for i in range(10):
time.sleep(2)
self.loading_pb.update_bar(pb_increment)
print(self.loading_pb.value)
This bit of code blocks the gui until it returns, so none of the normal gui drawing takes place. Instead, use Clock.schedule_interval
and/or Clock.schedule_once
to schedule each iteration of the loop. These insert the function call into kivy's own eventloop, and avoid blocking that loop.