I'm trying to write a program with python tkinter.
I wonder if it's possible to show a message or window without pausing the program?
For example, I want to show the status of the program (starting, waiting, finished)
but it seems like when the 'waiting' message/window is displaying, the program won't continue unless I close the window manually.
This is what I have now
from tkinter import *
root = Tk()
root.geometry('200x200')
root.configure(bg='gray92')
root.mainloop()
print(1)
root1 = Tk()
root1.geometry('200x200')
Message(root1, text="waiting...").pack()
root1.mainloop()
print(2)
I had to close the second window to print 2.
Is it possible to print 2 without closing the second window??
Related
I am making a python script that shows content in the console for the first 10-20 seconds after executed before the tkinter UI is shown. So is there any lines I can add to control the visibility of the console? .pyw file extension completely disables the console but I need the console to occasionally show up. Any suggestions?
First of all, you need to write your entire Tkinter code under a function.
def main_program():
# root = Tk() ...
Below this you need to write an empty print statement for the console. Below this, you can write anything. But the problem is sometimes, console quickly opens, prints the statement and closes it, so you barely have time to see
So, use time.sleep() -
import time
from tkinter import *
def main():
root = Tk()
root.mainloop()
print('Wait for a second')
time.sleep(1)
main()
This will show the print statement, delay the program for 1 second, and then open Tkinter window.
There are 2 ways to do it.
You can withdraw the window, print whatever you want and at the last, make it visible. .withdraw basically hides the window without any changes to the widgets.
from tkinter import *
root=Tk()
root.withdraw()
print("Hey there! Please wait for 10 seconds for the app to start...")
root.after(10000,lambda: root.deiconify())
root.mainloop()
Or, the second one is
from tkinter import *
import time
def create_window():
root = Tk()
root.mainloop()
print('Hey there! Please wait for 10 seconds for the app to start...')
time.sleep(10)
create_window()
I have a very simple python code: a tkitner button that process some images in the background. I wanted to open a tkinter toplevel to show the user that it was doing something, but for my surprise is not working as I thought it would. The command on the tk.Button is the next method:
def processing(self):
"""Starts the images processing"""
# Open a Tk.Toplevel
aux_topLevel = Splash(self.window) # a simple Tk.Toplevel class, that works perfectly
self._process_images() # starts processing the images
# I wanted to kill here the topLevel created before
aux_topLevel.destroy()
My surprise: the window is displayed once the processing images is done (tried it out adding prints and time.sleep), however, i couldn't display the TopLevel when I wanted to.
Is there anything am I doing wrong? Any help is appreciated. Thank you.
Consider the following example and try to run it.
What you'd think should happen is that the new Toplevel window should open, some event happens for a period of time and then the window is destroyed.
What actually happens is the window is opened, but never displayed, the task occurs and then the window is destroyed.
from tkinter import *
import time
def processing():
new = Toplevel(root)
new.geometry("200x150")
lbl = Label(new,text="--")
lbl.grid()
for i in range(50):
time.sleep(0.1)
#Un-comment the line below to fix
#root.update()
print(i)
lbl['text'] = "{}".format(i)
new.destroy()
root = Tk()
root.geometry('200x100')
btnGo = Button(root,text="Go",command=processing)
btnGo.grid()
root.mainloop()
If you un-comment out the root.update() line and re-run the code, the window will be displayed.
There are better ways to deal with tasks that takes a while to process, such as threading.
I am currently coding a program that will do something (e.g count numbers constantly) until something is inputted into a dialog box displayed.
However, whenever I try this, the program freezes when waiting for an input and so does not make any progress in the counting process I am trying to run in the background.
Is there any way to have a timer that continuously runs in the background so that in say 5 minutes, the counter instantly stops and the dialog box disappears? This is a basic skeleton of my code. I used the tkinter dialog box for input and tried to create a timer that will run in the background.
from time import *
from tkinter import *
from tkinter import messagebox
from tkinter import simpledialog
while timer<300:
sleep(1)
timer += 1
ROOT = Tk()
ROOT.withdraw()
USER_INP = simpledialog.askstring(title="Code Required",
prompt="What's the Code?:")
Preferably without external modules but if not that is fine. Thanks in advance :)
This is the code requested
from tkinter import *
from tkinter import simpledialog
root = Tk()
root.withdraw()
def ask():
simpledialog.askstring(title="Code Required",
prompt="What's the Code?:")
## root.after(5000, root.destroy()) #added in the root.after() to try and terminate it after set time
root.after(3000,ask) #triggers ask() after 3000 ms(3 seconds)
root.after(100000, root.destroy()) # tried to wait 10 seconds before it breaks but this doesn't show the dialog box any more
root.mainloop()
Here is a basic code with tkinter that makes the dialogbox pop up after 5 seconds.
from tkinter import *
from tkinter import simpledialog
root = Tk()
root.withdraw()
def ask():
simpledialog.askstring(title="Code Required",
prompt="What's the Code?:")
root.after(5000, root.destroy) #added in the root.after() to try and terminate it after set time
root.after(3000,ask) #triggers ask() after 3000 ms(3 seconds)
#root.after(10000, root.destroy) # tried to wait 10 seconds before it breaks but this doesn't show the dialog box any more
root.mainloop()
Here after() triggers a function after the given time, i.e, 3000 ms(3 sec), so you can adjust the timer, out there too. This is just an example and you can edit this more as you like.
Why use after() and not while and a timer?
This is because a while loop interferes a tkinter mainloop() causing the window to be unresponsive, so it is not recommended to use while or time.sleep(). Instead you could use the built-in after() method by tkinter or threading too.
Here is a bit more on after():
It takes two positional arguments,mainly, ms and func
ms - It is the time(in milliseconds) after which the specified function will be triggered.
func - It is the function to be triggered after the specified ms finises.
WARNING:
Keep in mind that the root window is not destroyed, its just hidden, so as long as the root window is not destroyed, the program keeps on running in the background, so you will have to bring back the window and close it for the task to end. For this reason, ive added root.destroy() there.
Take a look here for a bit more understanding on after()
Hope it cleared your doubts, do let me know if any errors.
Cheers
I'm using Tkinter to create a GUI program on python 2.7.
At some point, I want to open an informative window and close it automatically later on, the problem is, when I call quit on it the whole application closes.
root = tk.Tk()
root.title("WINDOW")
def create_wnd(xxx, yyy):
yyy.destroy()
def run_wnd():
dialog = tk.Toplevel()
dialog.title("wnd2")
wnd_run_button = tk.Button(root, text="RUN", command=lambda:run_wnd())
wnd_run_button.pack()
root.mainloop()
Put "the rest of the application" after the call to mainloop. Killing the window causes mainloop to exit, but any code after that will continue to run.
Or, put all of the window code inside a function that finishes by calling `mainloop, so the function won't exit until the window is destroyed. The code that calls the function will continue as soon as the function returns.
I am trying to make a game, at the end of the game I want it to bring up a window that says "You are" and then when you close that window, or maybe after a time limit, it will open another window with the character here's what I have tried:
def Youare():
You_are= Toplevel()#I have tried making this Tk() as well
You_are.geometry('+700+100')
says = Label(You_are,text ='You are....',font=('Helvetica',74))
says.pack(side=BOTTOM)
You_are.mainloop()#If I take this out both windows display at the same time
def Percy():
Percy= Toplevel()
Percy.geometry('450x450')
says = Label(Percy,text ='We were just looking at maps')
says.pack(side=BOTTOM)
img = ImageTk.PhotoImage(Image.open('C:/Users/Geekman2/Pictures/Pictures/Percy.jpg'))
image1 = Label(Percy,image=img)
image1.pack()
Percy.mainloop()
Youare()
Percy()
if you run Youare with the mainloop, Percy() won't run until the master window closes, if you run it without the mainloop, they both display at the same time, thus killing the suspense. What am I doing wrong?
The usual way to avoid calling several mainloop is to do something like
def Youare(master):
You_are = Toplevel(master)
#...
master = Tk()
Youare(master)
master.mainloop()
Then you will have to bind an action on your first window, have a look at these answer.