In Tkinter, I have a window that I would like to create when a process is initialized to run another Python script, which would then close when the script completes. Below is what I have so far:
window = tk.Toplevel()
window.geometry("400x90")
window.wm_title("Process is Running")
process = subprocess.Popen("python3 run_a_script.py", shell=True)
process.wait()
window.destroy()
The script is running, but the popup window never appears. It does appear after the script completes if I remove window.destroy()
, but it does not automatically close.
Is there a way to have the window be created before run_a_script.py is run, and then have it automatically close when the script completes?
CodePudding user response:
If I'm interpreting this right, then you never tell the window to "appear". Try adding:
window.update_idletasks()
window.update()
or
window.mainloop()
to show the window
Edit: Also, I typically use tk.Tk() for the main window instead of tk.Toplevel() for clarity. What's the difference between tkinter's Tk and Toplevel classes?
CodePudding user response:
All tkinter updates are handled by the tkinter mainloop
and during the execution of the external script, tkinter mainloop
does not take the control until after window.destroy()
, so you cannot see the window because it has been destroyed when tkinter takes back the control.
To show the window during the execution of the external script, you can:
- call
window.update_idletasks()
before callingsubprocess.Popen(...)
to let tkinter to show the window. However you cannot interact with the GUI during the execution of the external script.
window = tk.Toplevel()
window.geometry("400x90")
window.wm_title("Process is Running")
window.update_idletasks() # show the window
process = subprocess.Popen(["python3", "run_a_script.py"])
process.wait()
window.destroy()
- use
.after()
to check periodically whether the process has completed or not.
window = tk.Toplevel()
window.geometry("400x90")
window.wm_title("Process is Running")
process = subprocess.Popen(["python3", "run_a_script.py"])
def check_process():
if process.poll() is None:
# process is still running, check again 100ms later
window.after(100, check_process)
else:
# prcoess is completed, destroy the window
window.destroy()
check_process() # start the checking