Creating a simple progress bar or loading animation in Kivy?

I am writing a Kivy UI for the cmd line utility that I developed. Everything works fine, but some processes can take from a few seconds to several minutes, and I would like to give the user some idea that the process is running. Ideally, it should be in the form of a spinning wheel or a loading bar or something else, but even if I could update my display to show the user that the process was running, it would be better than mine.

Currently, the user presses a button in the main user interface. This brings up a pop-up window that checks some key information with the user, and if they are happy with these parameters, they click the Run button. I tried to open a new popup to let them know that the process is running, but since the display does not refresh until the process completes, this does not work.

I have a lot of experience writing code, but mainly in the field of mathematics and engineering, so I am very new to the development of interfaces and the need to handle events and threads. A simple standalone example would be greatly appreciated.

+7
source share
2 answers

I recently solved the problem you described: display doesn't update until the process finishes

Here is a complete example of how I worked with @andy_s on the #Kivy IRC channel:

My main.py:

 from kivy.app import App from kivy.uix.popup import Popup from kivy.factory import Factory from kivy.properties import ObjectProperty from kivy.clock import Clock import time, threading class PopupBox(Popup): pop_up_text = ObjectProperty() def update_pop_up_text(self, p_message): self.pop_up_text.text = p_message class ExampleApp(App): def show_popup(self): self.pop_up = Factory.PopupBox() self.pop_up.update_pop_up_text('Running some task...') self.pop_up.open() def process_button_click(self): # Open the pop up self.show_popup() # Call some method that may take a while to run. # I'm using a thread to simulate this mythread = threading.Thread(target=self.something_that_takes_5_seconds_to_run) mythread.start() def something_that_takes_5_seconds_to_run(self): thistime = time.time() while thistime + 5 > time.time(): # 5 seconds time.sleep(1) # Once the long running task is done, close the pop up. self.pop_up.dismiss() if __name__ == "__main__": ExampleApp().run() 

My .kv example:

 AnchorLayout: anchor_x: 'center' anchor_y: 'center' Button: height: 40 width: 100 size_hint: (None, None) text: 'Click Me' on_press: app.process_button_click() <PopupBox>: pop_up_text: _pop_up_text size_hint: .5, .5 auto_dismiss: True title: 'Status' BoxLayout: orientation: "vertical" Label: id: _pop_up_text text: '' 

If you run this example, you can click the Click Me button, which should open the “progress bar” as a modal / pop-up window. This popup will remain open for 5 seconds without blocking the main window. After 5 seconds, the popup will be automatically rejected.

+7
source

I came across a similar problem, and creating a new topic did not help. I had to use Clock.schedule_once(new_func) . He plans to call the function to the next frame, so it will execute almost immediately after the callback completes.

0
source

Source: https://habr.com/ru/post/988385/


All Articles