Executing a command before window.destroy() in tkinter - python

I am learning to build basic GUIs with Tkinter in order to use it in a project.
I would like to have a button that runs a certain task, then prints "Task done", then waits 1 second, and then closes the window.
Here's what I tried to do :
from tkinter import *
from time import *
def PrintAndClose():
label.configure(text="Task done")
t1 = time()
t2 = time()
while t2-t1 < 1:
t2 = time()
window.destroy()
window = Tk()
window.title("Task doer")
window.geometry('400x400')
label = Label(window, text="Task to be done")
label.pack()
bouton = Button(window , text = "Do the task", command=PrintAndClose)
bouton.pack()
window.mainloop()
When I run the GUI and click the button, it waits 1 second and then closes the window, but it does not change the label.
Is there anything wrong in what I'm doing ? I guess it's more complicated than that.
Thanks for your help !

It turns out using the after method as Matiss suggested fixed it.

Related

How do I make my button go away and How do i implement my code after a button is pressed?

Im just starting out and have made a timer and stuff succesfully but now wanted to make a GUI since its not that straight forward and I want to have a good project.
I want to know how to remove a button after I press it and how to start my timer code after i take an entry for how long I want my timer to last. Here is my timer code:
import time
from playsound import playsound
a = int(input("How long would you like your time to be(In Minutes): "))
with alive_bar() as bar:
b = a * 60
time.sleep(b)
bar()
playsound(r"C:\Users\shavi\Music\mixkit-arcade-retro-game-over-213.wav")
print("done"
and here is my gui code
from tkinter import *
#First creating my window
timer = Tk()
#My window name and dimension
timer.title("My Timer")
timer.geometry('400x200')
#My Command
def clicked():
lbl.configure(text = "Starting Timer")
#Label text
lbl = Label(timer, text ="Start a timer?")
lbl.grid()
#Button
button = Button(timer, text = "Yes",
command=clicked,)
button.grid(column=2, row=0)
#Running
timer.mainloop()
I tried using the .after but cant figure it out pleae help me figure this out

How to make a speedrun timer stay to the front

I made an in game timer for Minecraft to use while speedrunning and it works great but the one problem is that when I make Minecraft fill my whole screen NOT FULLSCREEN just cover it the timer disappears.
I knew this would happen and I am wondering if this is possible to fix and make the pygame window go to the front even if it is blocked by an app that you are currently using.
You can do this with Tkinter:
This way, you can make a timer:
Always put to front
Transparent
Furthermore, tkinter is in the Standard library.
You can use this code:
from tkinter import *
from threading import Thread
from time import time
tk = Tk()
tk.title('Timer')
tk.wm_attributes('-topmost', 1) # put the window to front
pause = True
start = time()
time_when_paused = time() # time displayed when in pause
def restart(): # restart to 0
global pause, start
pause = False
start = time()
def toggle_pause():
global pause, start, time_when_paused
pause = not pause
if pause:
time_when_paused = time() # update the time displayed
else:
start += time() - time_when_paused # forget the time passed in pause
def timer():
while True:
if pause:
label['text'] = '%.2f' %(time_when_paused - start) # %.2f for 2 decimals
label['fg'] = 'orange'
else:
label['text'] = '%.2f' %(time() - start)
label['fg'] = 'green'
label = Label(tk, '', font=('Helvetica', 30), fg='orange')
label.grid(columnspan=2) # display the timer
# buttons
restart_button = Button(tk, text='Restart', width=20, command=restart)
restart_button.grid(padx=5, pady=5)
pause_button = Button(tk, text='Pause', width=20, command=toggle_pause)
pause_button.grid(padx=(0, 5), column=1, row=1)
timer_thread = Thread(target=timer)
timer_thread.start() # put in a thread because of...
tk.mainloop() # ...this which acts like "while window is not closed"

Sleep while loop without break it, for write new entry in tkinter

In this UI there is 2 buttons and 1 entry box. Buttons named "Start Loop" and "Print".
When i write a text into the entry box, i should able to see it's print out when pressed the related button. What i am trying to do is, put that button press in a while loop. But the interesting part is trying to print a new entry in every 10 seconds.
When you entered a entry and press the "Start Loop" button, it becomes run. Meanwhile user interface window will froze. Can't write a new entry or press "Print" button. Even i use time.sleep function it still frozen. It prints old entry, but i want to write a new entry at every iteration. Check out the code:
import time
from tkinter import *
class tkin(Frame):
def __init__(self,parent):
Frame.__init__(self, parent)
self.parent = parent
self.UI()
def UI(self):
self.down = StringVar()
self.down_entry = Entry(self, textvariable=self.down)
self.down_entry.grid(row=2, column=0)
self.start_loop_buuton = Button(text="Start Loop", command=self.loop_func)
self.start_loop_buuton.place(x=10,y=40)
self.print_func_button = Button(text="Print ", command=self.pprint)
self.print_func_button.place(x=120,y=40)
self.pack()
def loop_func(self):
start = time.time()
while True:
print("standart print out")
end = time.time()
if (end- start) >10:
time.sleep(10)
self.print_func_button.invoke() ## press print_func_button
start = time.time()
def pprint(self):
print("WHICH PRINT LINE I WANT TO PRINT IN LIKE EVERY 10 SECONDS")
print(self.down.get())
def main():
root = Tk()
tkin(root)
root.geometry("195x100+300+300")
root.mainloop()
main()
Any advice would be nice. Thanks in advance.
this is how I would redefine Your method:
def loop_func(self):
self.print_func_button.invoke() # press print_func_button
self.after(3000, self.loop_func)
time is in miliseconds so this will be 3 seconds
In this example, i just separated the looping "loop_func()" using thread in Button function's argument of command. Like that:
import threading
...
...
...
self.start_loop_buuton = Button(text="Start Loop", command=threading.Thread(target=self.loop_func).start())
So, these two loops have been separated.

Python Set Button Text While busy

I'm new to python and I am trying to create a program but I can't even get the basics right. I have a button app that looks like this:
#simple GUI
from tkinter import *
import time
#create the window
root = Tk()
#modify root window
root.title("Button Example")
root.geometry("200x50")
button1state = 0
def start():
count = 0
button1["text"] ="Busy!"
while (count < 5):
root.after(1000)
count = count + 1
def button1clicked():
global button1state
if button1state == 0:
start()
button1["text"] ="On!"
button1state = 1
else:
button1["text"] ="Off!"
button1state = 0
app = Frame(root)
app.pack()
button1 = Button(app, text ="Off!", command = button1clicked)
button1.pack()
#kick off the event loop
root.mainloop()
Now everything works except it doesn't change the button text to busy while
**start()** is called. How can I fix this? Once I've got it working I want to use images to show the user that its OFF ON and BUSY. Please help me
You need to force the GUI to update before starting the task:
def start():
count = 0
button1.configure(text="Busy!")
root.update() # <-- update window
while (count < 5):
root.after(1000)
count = count + 1
But if you don't want your GUI to be frozen while the task is executed, you will need to use a thread as Dedi suggested.
You have to make a thread in order to make you function as a "background event" while your interface is working. Consider using that :
from threading import Thread
and then :
my_thread=Thread(target=start())
my_thread.start()
Where the first "start()" is the name of your function and the second one a call for the thread to begin.

How to make a button print out certain text? - Tkinter

Below, I have created a code to track the laps a person who is running. At the moment, the button I had created tracks the laps and the time, but not on the GUI window. I was wondering how to make the data on the from the code show on the GUI window.
from Tkinter import *
import time
laps=[0]
gui=Tk()
gui.geometry("200x100")
gui.title("lapping")
def afterbutton():
label_1=Label(gui,text=end())
def end():
end = time.time()
elapsed = end - start
laps[0]+=1
print "%s seconds" % (elapsed)
print "%s lap(s)" % (laps)
starting = raw_input("start? (s to start)")
if starting == "s":
start = time.time()
button1=Button(gui,command=afterbutton,text="lap")
button1.grid()
button1.pack()
gui.mainloop()
You need to create the label at the same time you create the button. You need to put it in the grid and pack it, just like you did with the button. Then when the button is clicked, all you have to do is change the label's text. This is what it looks like:
# python 3
from Tkinter import *
import time
laps=[0]
gui=Tk()
gui.geometry("200x100")
gui.title("lapping")
def end():
end = time.time()
elapsed = end - start
laps[0] += 1
s = "%s seconds %s laps" % (elapsed,laps)
label1['text'] = s
print("%s seconds" % (elapsed))
print("%s lap(s)" % (laps))
starting = raw_input("start? (s to start)")
if starting == "s":
start = time.time()
button1 = Button(gui, command=end, text="lap")
button1.grid()
button1.pack()
label1 = Label(gui)
label1.grid()
label1.pack()
gui.mainloop()
The function afterbutton is gone; all the work is done by end(). I kept most of your program, but I'm using py3 so print is a function rather than a statement. You'll have to fix that for py2. The text of the label is set by:
label1['text'] = s
which is a somewhat weird syntax when you first see it.
BTW, I don't see why you used a 1-element list for laps instead of a simple variable.

Categories

Resources