Progress bar in pop-up in Python Kivy

Introduction

I thought about displaying the progress of the function with the progress bar widget installed in Kivy's pop-up widget. By using the function for which you want to display the progress as a generator, it looks as if the progress bar is being updated from within the function.

environment

Customize pop-up widget

Use the following image pop-up consisting of three parts: progress bar, label, and button. 2017-04-23_14h29_40.png

In addition, the following two methods have been added to the pop-up widget.

  1. set_value (): Method to update the value and label of the progress bar
  2. ʻenable_close_button ()`: Method to enable the button to close the popup

The code is as follows.

Class-PopupProgress


from kivy.uix.boxlayout import BoxLayout
from kivy.uix.progressbar import ProgressBar
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.label import Label

class PopupProgress():
    def __init__(self, value_init=0, value_max=1, title='', size=None, 
                 auto_close=False):
        self._auto_close = auto_close
        self._box = BoxLayout(orientation='vertical')
        
        if size is None:
            size_hint = (1,1)
        else:
            size_hint = (None, None)
        
        self.popup = Popup(title=title, 
                           content=self._box, 
                           auto_dismiss=False, 
                           size_hint=size_hint, 
                           size=tuple(size)
                           )
        
        # progress bar
        self._pb = ProgressBar(max=value_max, value=value_init)
        self._box.add_widget(self._pb)
        
        # label
        self._label = Label(text='')
        self._box.add_widget(self._label)
        
        # close button
        self._button = Button(text='Close', height=40, size_hint_y=None, 
                        disabled=True)
        self._button.bind(on_press=self.popup.dismiss)
        self._box.add_widget(self._button)
        
        self.popup.open()    #Open a pop-up
        
        
    def set_value(self, value=None, message=''):
        if not value is None:
            self._pb.value = value
        self._label.text = message
        if self._pb.value_normalized>=1:
            if self._auto_close:
                self.popup.dismiss()
            else:
                self.enable_close_button()
    
    
    def enable_close_button(self):
        self._button.disabled = False
        

Root Widget In addition to the constructor (\ _ \ _ init \ _ \ _) for creating buttons, the Root Widget has the following three methods.

  1. func_test (): Method (generator) that wants to check the progress of time-consuming processing

--The method that wants to check the progress of time-consuming processing is a generator. --The yield value, message is inserted in the place where you want to check the progress of the process, and the progress and message are returned. --At the end of the process, value = 1 is returned and the close button is enabled. --Here, Max value = 1 of the progress bar is set, but any value can be set with func_test_pp (). --Here, time.sleep (1) is set to imitate the time-consuming process.

  1. func_test_pp (): Method to start a loop to update the value of the progress bar

--Create an instance of the pop-up widget class self.pp. --Create an iterator object self.gen from the abovefunc_test ()generator. --Use the Clock.schedule_once () to execute the recursive method pp_update () to start the loop.

  1. pp_update (): Recursive method to update the value of the progress bar

--After referencing the iterator object self.gen once, update the value of the progress bar. --Use Clock.schedule_once () to call itself again until you get a StopIteration or other error. --If an error occurs, the button in the pop-up is enabled so that the user can close the pop-up.

Class-RootWidget etc.


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

class RootWidget(BoxLayout):
    
    def __init__(self, **kwargs):
        super(RootWidget, self).__init__(**kwargs)
        button = Button(text='popup!')
        button.bind(on_press=self.func_test_pp)
        self.add_widget(button)
        
        
    def pp_update(self, *args):
        try:
            value, message = next(self.gen)
            self.pp.set_value(value, message)
            Clock.schedule_once(self.pp_update, 0.1)
        except StopIteration:
            self.pp.enable_close_button()
        except Exception as e:
            self.pp.set_value(message=str(e))
            self.pp.enable_close_button()
    
    
    def func_test_pp(self, *args):
        self.pp = PopupProgress(
                title='TestPopupProgress', 
                size=(self.width/2, self.height/3)
                )
        self.gen = self.func_test()
        Clock.schedule_once(self.pp_update, 0.1)
    
    
    def func_test(self):
        yield 0, 'Preparing...'    #Use yield to return current progress and comments (beginning)
        
        #Time-consuming processing that you want to check the progress
        allitems = 5
        for i in range(allitems):
            time.sleep(1) #Something time-consuming process
            yield (i+1)/allitems, '{:d}/{:d}'.format(i+1, allitems)    #Use yield to return current progress and comments
        
        yield 1, 'Complete.'    #Use yield to return current progress and comments (end)
        
        
class TestPopupProgressApp(App):
    def build(self):
        return RootWidget()
    
    
if __name__ == '__main__':
    TestPopupProgressApp().run()

Summary

The above can be summarized as follows. 2017-04-23_14h33_04_.gif

test_popup_progress.py


from kivy.app import App

from kivy.clock import Clock

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.progressbar import ProgressBar
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.label import Label

import time

class PopupProgress():
    def __init__(self, value_init=0, value_max=1, title='', size=None, 
                 auto_close=False):
        self._auto_close = auto_close
        self._box = BoxLayout(orientation='vertical')
        
        if size is None:
            size_hint = (1,1)
        else:
            size_hint = (None, None)
        
        self.popup = Popup(title=title, 
                           content=self._box, 
                           auto_dismiss=False, 
                           size_hint=size_hint, 
                           size=tuple(size)
                           )
        
        # progress bar
        self._pb = ProgressBar(max=value_max, value = value_init)
        self._box.add_widget(self._pb)
        
        # label
        self._label = Label(text='')
        self._box.add_widget(self._label)
        
        # close button
        self._button = Button(text='Close', height=40, size_hint_y=None, 
                        disabled=True)
        self._button.bind(on_press=self.popup.dismiss)
        self._box.add_widget(self._button)
        
        self.popup.open()
        
        
    def set_value(self, value=None, message=''):
        if not value is None:
            self._pb.value = value
        self._label.text = message
        if self._pb.value_normalized>=1:
            if self._auto_close:
                self.popup.dismiss()
            else:
                self.enable_close_button()
    
                    
    def enable_close_button(self):
        self._button.disabled = False
        
class RootWidget(BoxLayout):
    
    def __init__(self, **kwargs):
        super(RootWidget, self).__init__(**kwargs)
        button = Button(text='popup!')
        button.bind(on_press=self.func_test_pp)
        self.add_widget(button)
        
        
    def pp_update(self, *args):
        try:
            value, message = next(self.gen)
            self.pp.set_value(value, message)
            Clock.schedule_once(self.pp_update, 0.1)
        except StopIteration:
            self.pp.enable_close_button()
        except Exception as e:
            self.pp.set_value(message=str(e))
            self.pp.enable_close_button()
    
    
    def func_test_pp(self, *args):
        self.pp = PopupProgress(
                title='TestPopupProgress', 
                size=(self.width/2, self.height/3)
                )
        self.gen = self.func_test()
        Clock.schedule_once(self.pp_update, 0.1)
    
    
    def func_test(self):
        yield 0, 'Preparing...'
        
        allitems = 5
        for i in range(allitems):
            time.sleep(1)
            yield (i+1)/allitems, '{:d}/{:d}'.format(i+1, allitems)
        
        yield 1, 'Complete.'
        
        
class TestPopupProgressApp(App):
    def build(self):
        return RootWidget()
    
    
if __name__ == '__main__':
    TestPopupProgressApp().run()

Recommended Posts

Progress bar in pop-up in Python Kivy
The one that displays the progress bar in Python
bar chart race in python
GUI programming using kivy ~ Part 2 Progress bar ~
[Python] Progress display by progress bar using tqdm
[Python] A progress bar on the terminal
Quadtree in Python --2
CURL in python
Metaprogramming in Python
Python 3.3 in Anaconda
Geocoding in python
SendKeys in Python
Meta-analysis in Python
Unittest in python
Epoch in Python
Discord in Python
Sudoku in Python
DCI in Python
quicksort in python
nCr in python
N-Gram in Python
Programming in python
Plink in Python
Constant in python
Lifegame in Python.
FizzBuzz in Python
Sqlite in python
StepAIC in Python
N-gram in python
LINE-Bot [0] in Python
Csv in python
Disassemble in Python
Reflection in Python
Constant in python
nCr in Python.
format in python
Scons in Python3
Puyo Puyo in python
python in virtualenv
PPAP in Python
Quad-tree in Python
Reflection in Python
Chemistry in Python
Hashable in python
DirectLiNGAM in Python
LiNGAM in Python
Flatten in python
flatten in python
Make progress of dd visible in the progress bar
Sample to put Python Kivy in one file
I want to display the progress in Python!
Sorted list in Python
Daily AtCoder # 36 in Python
Clustering text in Python
Daily AtCoder # 2 in Python
Implement Enigma in python
Daily AtCoder # 32 in Python
Daily AtCoder # 6 in Python
Edit fonts in Python
Singleton pattern in Python
Download the file while viewing the progress in Python 3.x