1

I'm trying to write a kivy application that allows the user to clear the database, essentially resetting the app to default. The problem I'm having is that when the user clicks the button to clear and reset the database (the "clear database" button on the settings streen), it's a bit of a long process, and I'd like a popup box to display a spinning gif to appear until the process ends.

The problem is that both the popup and the cleardatabase processes seem to be happening at the same time, so that the the popup only flashes on and then disappears at the end of the cleardatabase process.

I've explored different posts and tried solutions therein, but nothing seems to work.

Below I've included stripped-down code derived from my actual code that replicates the problem, with the cleardatabase method invoking a sleep(5) to mimic the long process. In this most recent attempt, I've modeled the code after the solution in this post. Perhaps the problem is that I'm using ScreenManager?

This is all in python2.7, by the way, and kivy 1.9.1 I think.

Thanks in advance for any help.

main.py

from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.popup import Popup
from kivy.uix.image import Image
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.uix.anchorlayout import AnchorLayout
from kivy.properties import NumericProperty, ReferenceListProperty, ObjectProperty, \
        StringProperty
from kivy.event import EventDispatcher
import threading, time


class SightwordsGame(Screen):
    word = StringProperty('Screen1')

    def SwitchToSettings(self):
        self.manager.current = 'settings'
        SettingsScreen = self.manager.get_screen('settings')

class SettingsScreen(Screen):

    def poptest(self):
        time.sleep(5)

    def ClearDatabase(self):
        self.popup = Popup(title='Test popup', content=Image(source='waiting.gif'), 
                           auto_dismiss=False, size_hint=(None, None), size=(400, 400))
        self.popup.open()
        mythread = threading.Thread(target=self.poptest())
        mythread.start()
        self.popup.dismiss()

class SightwordsApp(App):
    def build(self):
        sm = ScreenManager()
        screen1 = SightwordsGame(name='main')
        screen2 = SettingsScreen(name='settings') 
        sm.add_widget(screen1)
        sm.add_widget(screen2)

        return sm

if __name__ == '__main__':
    SightwordsApp().run()

sightwords.kv

#:kivy 1.9.1

<MenuButton@Button>:
    font_size:40
    color: 0,1,0,1
    size_hint: 0.3, 0.2

<SightwordsGame>:
    AnchorLayout:
        anchor_x: "center"
        anchor_y: "center"
        Label:
            font_size: root.width/4
            text: root.word
    AnchorLayout:
        anchor_x: "left"
        anchor_y: "bottom"
        Image:
            source:'gear.png'
            size_hint: 0.1,0.1
            on_touch_down: if self.collide_point(*args[1].pos): root.SwitchToSettings()

<SettingsScreen>:
    GridLayout:
        cols: 2
        row_force_default: True
        row_default_height: root.height/6
        Label:
            text: "Clear database:"
            size_hint_x:None
            width:root.width/3
        Button:
            text: "Press here to clear"
            on_press: root.ClearDatabase()
    AnchorLayout:
        anchor_x: "left"
        anchor_y: "bottom"
        Image:
            source: 'arrow.png'
            on_touch_down: if self.collide_point(*args[1].pos): root.manager.current = 'main'
            size_hint: 0.1,0.1
Zederick
  • 13
  • 2

1 Answers1

0

You start thread and immediately close the popup. You should close the popup when the thread ends, so you should close it from the thread:

class SettingsScreen(Screen):

    def poptest(self):
        time.sleep(5)
        self.popup.dismiss()

    def ClearDatabase(self):
        self.popup = Popup(title='Test popup', content=Image(source='waiting.gif'), 
                           auto_dismiss=False, size_hint=(None, None), size=(400, 400))
        self.popup.open()
        mythread = threading.Thread(target=self.poptest)
        mythread.start()
FJSevilla
  • 3,733
  • 1
  • 13
  • 20
  • Thanks for the response. Your answer is consistent with [the post I referenced](https://stackoverflow.com/questions/30595908/building-a-simple-progress-bar-or-loading-animation-in-kivy) in my original question. Unfortunately, when I move self.popup.dismiss() up to the poptest() method, I get the exact some result--the popup just flashes on and off after 5 seconds have already passed. – Zederick Jul 15 '17 at 23:11
  • @Zederick it's very strange ... I've tested the code in Python 2.7.13 / Kivy 1.9.1 and in Python 3.6.1 / Kivi 1.10 and I can´t reproduce the problem. The popup stays on screen for 5 seconds as expected. – FJSevilla Jul 15 '17 at 23:23
  • @Zederick I'm sorry, there was an error I've overlooked: you must pass the function name to the `target` argument (you should not use parentheses). I have corrected it in the answer. – FJSevilla Jul 15 '17 at 23:36