Reputation: 155
For some process in my app, I use the internet to acquire some data. So for those processed I want a simple popup box(with a text Loading...) to appear at the begining of the process, but when I ran the test code, I observed that the popup box displays at the end of the process rather than at the begining of the process which makes it useless. Here is the test code I am using. Your help is appreciated, thanks.
class ScreenManagement(ScreenManager):
def popup(self):
self.pop_up=Popup(title='Loading...')
self.pop_up.open()
def popup_done(self):
self.pop_up.dismiss()
def ite(self):
for i in range(100):
App.get_running_app().root.current='second'
return i
def thread_it(self,fx):
self.popup()
mythread = threading.Thread(target=fx)
mythread.start()
def ite(self,num):
for i in range(num):
txt=str(i)*40
self.ids.lbl.text=txt
print txt
#if i==num-1: #this is not working
# self.popup_done()
class labelApp(App):
def build(self):
pass
labelApp().run()
.kv file
ScreenManagement:
Screen:
BoxLayout:
Button:
#on_press:root.popup()
#on_release:root.popup_done()
on_press:root.thread_it(root.ite(40000))
on_press:root.current='second'
Screen:
name:'second'
BoxLayout:
Label:
id:lbl
text: 'hello'
Upvotes: 1
Views: 707
Reputation: 12169
The problem is with your ScreenManagement.ite()
method. It doesn't run in thread and you've already noticed that anything that could compete with Kivy's main loop and doesn't run in Thread
will freeze the main loop. Kivy has Clock
which might interest you too.
For this exact code however you'll need partial
, which will freeze a function in time and return a thing you can pass as argument, so that it wouldn't be executed in-place where you want to add it as an argument to a thread function (e.g. if ite()
means executing, partial
will remove those brackets and let Thread
add them when it's necessary)
Thread(target=fx)
means after passing the ite()
method basically this:
Thread(target=root.ite(40000))
i.e. runs that thing in-place and as ite()
method doesn't return anything, it'll do this:
# freeze main loop
# after done, call Thread
Thread(target=None)
and starts it. So you freeze your main loop and after the ite()
ends, the Popup
gets its turn to show up. Let's fix it with partial
:
#:import partial functools.partial
<ScreenManagement>:
Screen:
BoxLayout:
Button:
#on_press:root.popup()
#on_release:root.popup_done()
on_press: root.thread_it(partial(root.ite,400))
on_press: root.current='second'
Upvotes: 2