0

The Python app I'm developing loads a largish initialization file from the net. The process is taking so long that the users are relaunching the app before the window can pop open. What I'm looking for is a way to pop open the apps tkinter window (with or without a loading message) before the app loads the network file. This will let the user know what is happening and keep them from relaunching the app.

In other words, how do I automatically run some code after the call to mainloop() to open the window, but before the user interface goes idle waiting for clicks?

Code I'm currently using to pop open the window:

winWid = 650
winHei = 390
window = tkinter.Tk()
window.geometry(str(winWid) + "x" + str(winHei))
window.title("AppTitle")
window.configure(bg="#FFFFDC")

# Load Initialization file - goal is to have this automatically happen after window opens

window.mainloop()

Edit: Launching an initialization thread might do the trick, but it seems like drastic over kill when all I want to do is populate a list in the gui with the contents of a network file.

codingCat
  • 2,396
  • 4
  • 21
  • 27
  • I would recommend to use two threads, but I dont think `tkinter` would communicate between two different threads. – Delrius Euphoria Mar 18 '21 at 18:21
  • Sounds like you need to look at [threading](https://docs.python.org/3/library/threading.html) – Alan Mar 18 '21 at 18:22
  • Not this is the sort of reason why programs originally used [splashscreens](https://en.wikipedia.org/wiki/Splash_screen) - you can have a small notification come up while another thread loads the config, then both shut down and move onto the main application – Alan Mar 18 '21 at 18:25
  • Adding a second thread seems like a drastic measure for my little app. I was hoping for something a little more straight forward. – codingCat Mar 18 '21 at 18:29
  • @codingCat You could have a prompt come up saying "Config file will load, this will take approx 10-15 minutes, please do not restart the program. Press OK to continue" and when they press OK, load the config file and finally load the main window. – Alan Mar 18 '21 at 18:32
  • @codingCat Also, how often does the config change? You could have a local copy and put a support script on the scheduler of a machine, the support script downloads an updated version of the config ready for when someone wants to run the application. – Alan Mar 18 '21 at 18:34
  • @codingCat Second thread seems perfect according to me. – Delrius Euphoria Mar 18 '21 at 18:34
  • The config file (the list it contains) changes daily. And yes, I do make a local copy so that subsequent loads each day take significantly less time. – codingCat Mar 18 '21 at 18:38
  • The question is now unclear, when do you want to load the data and how do you prefer to do it. – Delrius Euphoria Mar 18 '21 at 19:15
  • @CoolCloud I want the window to pop open as quickly as possible, without waiting for the network file to load. The file is a list of options for display in a listbox on the gui and is at the heart of the app, thus I want it to load asap. I also want the window to open asap to discouraging the user from relaunching it. Perfect would be to pop open the window, then load the file, all without user interaction. – codingCat Mar 18 '21 at 19:19
  • To be honest, you will have to speed up the process somehow, other than that I am not sure how you will get this done. If you are saying that the window does not even pop up, maybe try saying `root.update()` before starting the heavy process. – Delrius Euphoria Mar 18 '21 at 19:23
  • 1
    Try putting the loading task in a function, e.g. `loading_configs()` and call `window.after(100, loading_configs)` before `window.mainloop()`. Note that it is still blocking you from interacting with the window if `loading_configs()` is time-consuming task. – acw1668 Mar 19 '21 at 08:30

2 Answers2

2

The answer came from @CoolCloud and @acw1668 in the form of the after() method.

window.after(1, loadAndDisplay) # Wait for a single millisecond before calling
window.mainloop()               # Pop open the window

after(milliseconds,function,*args) will launch the given function after a millisecond timer expires. By making the timer a single millisecond, the function launches almost without delay. Documentation suggests that a delay of 0 will launch the method as soon as mainloop completes its setup. In practice however, I found that a zero cause the call to happen as soon as mainloop is called.

Further detail can be found at this link: tkinter: how to use after method

codingCat
  • 2,396
  • 4
  • 21
  • 27
1

What about you make a button and prompt them to start the process and then they can wait for it to finish instead of restarting the whole time. For example : Like in a app they ask you first to and then download or do whatever needs to be done.

from tkinter import *
root = Tk()


def process():
    pass
    #do your process here
    
    
btn1 = Button(root, text="Start process",command=process)
btn1.pack()

root.mainloop()
Rhino
  • 43
  • 6
  • The init file populates a list that supports the main purpose of the app. In other words, the app does nothing without the file. This is why I want to start this lengthy process before when the app launches rather than holding up the user waiting for them to start it. – codingCat Mar 18 '21 at 18:31
  • Ooh let me see what i can do – Rhino Mar 18 '21 at 18:32
  • 1
    But if the app does nothing without the file launching it and doing the task or not launching it does thr same thing – Rhino Mar 18 '21 at 18:32
  • The gui can exist without without the data from the file. It is just a lot of data to load into a list, and I want it to load automatically while still displaying the window as quickly as possible. – codingCat Mar 18 '21 at 18:36
  • Okay I think i can crack this – Rhino Mar 18 '21 at 18:37