0

My kivy popup does not appear on the screen until the rest of the code in my method finishes running. I am trying to display a progress bar so it is worthless in it's current state.

I have tried to thread the process to open the popup and tried without threading.

from kivy.uix.progressbar import ProgressBar
from kivy.uix.popup import Popup
import threading

def submit():
    popup = Popup(title='Submit Progress', content=ProgressBar())
    thread_object = threading.Thread(target=popup.open)
    thread_object.start()
    perform some iterable actions 
       increment progress bar value

    if progress_bar.value == progress_bar.max:
        popup.auto_dismiss = True
        # This is when the popup finally appears

I need the open function of my popup to actually take effect before performing the iterable actions so the user can watch the progress

  • You're trying to open the popup in a thread and run your processing in the main thread, but this is the wrong way around. Open the popup in the main thread, and run your incrementing process in another thread. – inclement Aug 30 '19 at 20:16
  • I have tried changing to the other way around as you suggest with the exact same result. Can you explain why you say it should be this way vs the other? Why does it matter? It may help me to understand what else I need to switch. @inclement – Alex Champe Sep 03 '19 at 18:27

2 Answers2

0

This is based on member 'inclement's' answer. I am not 100% what you are attempting to do but here is some code I tested that kicks off a long-running task in its own thread and holds the popup open until that task completes.

Kivy .kv file entry

Button:
    text: "do..."
    on_release: app.root.info_popup(self)  # your app may need root.info_popup(self)

In the app, the target method

def info_popup(self, _button: Button):
    print(str(type(_button)))
    popup_content = ProgressBar(max=10)

    popup = Popup(title="Countdown",
                  size_hint=(None, None), size=(400, 180),
                  content=popup_content,
                  auto_dismiss=False)
    print("starting a new thread to do the countdown")
    threading.Thread(target=partial(self.update_progress, an_object=popup_content,
                                    the_popup=popup), daemon=True).start()
    popup.open()

which starts this function as its own thread

def update_progress(self, an_object, the_popup: Popup):
    for i in range(10, -1, -1):
        time.sleep(1.0)
        print("progress: {}".format(i))
        an_object.value = i
    the_popup.dismiss()
    print("I have dismissed the popup")
Mark
  • 532
  • 1
  • 4
  • 9
  • This has not worked for me. My popup still refuses to open until the rest of the threads have completed. – Alex Champe Sep 03 '19 at 21:19
  • Alex, are you opening the popup from a button or similar in your main code? is this on windows/linux/mac or is this occurring when you run as a phone app? the example I pasted was running on Windows but it was spliced into my already-running app. When you set the target variable of a thread be very careful not to execute it target=myfun() is wrong and is a common error, but target=mufun is correct. – Mark Sep 03 '19 at 22:12
  • I am opening from a method within my main code that is called from a button press. I am not using the () within my target= piece of code. the popup.open() call just doesn't open the popup until later whether I thread the rest of my code or not. I have other popups in my application that open when called, as expected... – Alex Champe Sep 04 '19 at 15:06
  • Forgot to add that this is on windows. – Alex Champe Sep 04 '19 at 16:54
0

I solved the issue by using the Clock.schedule_once() function to schedule my other threaded updates.