I am working on a python tkinter program that monitoring computer temperature, and I want it to update the temperature value after a fixed time.
the following function is what I used to do that:
def update():
get_temp()#the function that get the computer temperature value, like cpu temperature.
...
def upd():
update()
time.sleep(0.3)
upd()#recursive call function.
upd()
but this way will hit the recursive limit, so the program will stops after a period of time.
I want it to keep updating the value, what should I do?
I don't know if I change it to after() it will be better or not.
but if I use after(), the tkinter window will freeze a while, so I don't want to use it.
Thank you.
It needs loop.
It should be:
def update():
get_temp()#the function that get the computer temperature value, like cpu temperature.
...
def upd():
while True:#needs a while true here and don't call upd() in this function.
update()
time.sleep(0.3)
upd()#this upd() is outside the function upd(),it used to start the function.
Thanks to everyone who helped me.
Recursion is inadequate in this use-case, use a loop instead.
Tkinter in particular has got a method which allows you to execute a function in an interval without disrupting the GUI's event loop.
Quick example:
from tkinter import *
root = Tk()
INTERVAL = 1000 # in milliseconds
def get_temp()
# ...
root.after(INTERVAL, get_temp)
get_temp()
root.mainloop()
Related
I have been through many examples about after cancel method in Tkinterbut I am not clear about that.In my code I am using the after method to enter the value of s in entry box after a certain time delay.Now i need to stop that after the cycle is completed when a button is pressed.
def read_pressure():
global s
s+=1
E3.delete(0,'end')
E3.insert(0,s)
top.after(1000, lambda:read_pressure())
Now i need to stop these loop using a button.How to do that??
I am using python 3.5
With the help of Dan i can able to stop after method.But it freezes my gui and I can't able to recall the after method.
How to do that?!
You need to keep the return value around:
handle = top.after(1000, lambda:read_pressure())
And then when the button is clicked do:
if handle:
top.after_cancel(handle)
handle = None
Both with global handle. I would prefer to make these methods and use self to store state than mutate globals.
I have to code a game with turtle library.
In the rules, there is an object that fells every X milliseconds until a certain condition is reached.
If I use sleep(), the screen does not respond anymore to the keyboard events. Is there any way to periodically call a function "asynchronously" ?
Many thanks !
Python turtle provides a one-shot:
screen.ontimer(my_function, milliseconds)
which you can turn into an every X milliseconds timer event:
def my_function():
pass # do whatever
if still_needed: # start again in the future if still needed
screen.ontimer(my_function, 100) # repeat every 0.1 second
I am trying to build a gambling dice game for fun using Python's Tkinter in Python 3. The error I am having is after the money is taken away from your bank account (it does this in a different function) I want it to go back to the mainloop. So basically I want to exit a function to get back into the main code (which isn't in a function). Any ideas on how?
I am not 100% sure what your problem is but it sounds like you might not fully understand how a function works.
In a tkinter application the mainloop() is always looping so once your function has finished the the next task in that loop will run and if no more task are scheduled in that loop the loop will reset.
Take this below code for example.
from tkinter import *
root = Tk()
def some_function():
print("this function just ran")
Button(root, text="Run some func", command = some_function).pack()
root.mainloop()
What we see is a button that allows us to call on some_function and then once that function is over we are "back in" the mainloop() so to speak.
There is nothing you need to do special here unless inside of your function you are running some kind of loop and want to end the loop on some criteria. Then you can use a break line to end that loop.
The function will automatically stop when it is finished running. Using return, though, will immediately exit the current function, perhaps before it gets through all of its code, if that's what you mean.
I've searched for a simple animation code with Tkinter but I've found very different examples and I can't understand the correct way to write an animation.
Here my working code to display a simple moving circle:
import tkinter as tk
import time
root=tk.Tk()
canvas=tk.Canvas(root,width=400,height=400)
canvas.pack()
circle=canvas.create_oval(50,50,80,80,outline="white",fill="blue")
def redraw():
canvas.after(100,redraw)
canvas.move(circle,5,5)
canvas.update()
canvas.after(100,redraw)
root.mainloop()
In this code I can't correctly understand: how the after method works, where correctly put the update and the move method (before after method ?), is there another way to write an animation code? may you post me another example and comment the code please?
Thanks :)
Calling update
You should not call canvas.update(). As a general rule of thumb you should never call update. For a short essay on why, see this essay written by one of the original developers of the underlying tcl interpreter.
If you take out the call to canvas.update(), you have the proper way to do animation in a tkinter program.
Calling after to start the animation
You don't need to call after immediately before calling root.mainloop(). This works just as well:
...
redraw()
root.mainloop()
The choice to use or not use after in this specific case is dependent on if you want the animation to start immediately (possibly even before the widget is visible) or if you want it to happen after a short delay (possibly after the widget is made visible)
How after works
mainloop is nothing more than an infinite loop that checks the event queue for events. When it finds an event, it pops it off of the list and processes it. after is nothing more than making a request that says "in 100 ms, please add a new event to the queue". When the time limit expires, an event is added to the queue that says, in effect, "run this command". The next time the loop checks for events, it sees this event, pulls it off of the queue, and runs the command.
When you call after from within a method that itself was called by after, you're saying in effect "wait 100ms and do it again", creating an infinite loop. If you put the call to after before moving the object, you're saying "every 100ms run this function". If you put it after you're saying "run this function 100 ms after the last time it was run". The difference is very subtle and usually not perceptible unless your function takes a long time to run.
my code is:
from tkinter import *
import time
tk = Tk()
płótno = Canvas(tk, width=500, height=500)
płótno.pack()
płótno.create_polygon(10,10,10,70,70,10,fill="blue",outline="black")
for x in range(0,51):
płótno.move(1,5,0)
płótno.update()
rest(0.05)
płótno means canvas
I wrote a modified program of the 'mines' game, and I hope it shows every step/click graphically. I use time.sleep(0.5) to make a pause. So, in general the main program is like:
check_block():
if mine == 0:
buttons[current].config(image = tile_clicked)
elif mine == 1:
buttons[current].config(image = tile[1])
...
while(1):
time.sleep(0.5)
check_block()
get_next()
if check_fail():
break
However, the buttons don't update every 0.5 second: they are all updated together when the game(loop) finishes.
I guess it's just like 'cout' in C++: if you don't flush they will get stacked. So, is there a method to get them updated step by step, or say, instantly?
Thanks!
In all GUI systems you have to allow the message loop to run so that Windowing events occur promptly. So do not use a while loop like this. Instead, create a method that calls check_block() and get_next() and use after to call that function after a delay. At the end of that function, you use after again to call the same function again so that this function is called every 0.5 second forever. The after function queues a timer event and then lets the message queue be processed. Once your timer event fires, the callback function is run which allows you to do things and keep the UI responsive.
You should never call sleep in a GUI program. This is because the GUI must be "awake" at all times so that it can service events (including internal events that cause the screen to update). Instead, leverage the already-running eventloop by using the after method to put events on the queue at regular intervals.
In your case, you would replace the while loop with something like:
def do_check():
check_block()
if not check_fail():
root.after(500, do_check)
# in your initialization code, start the loop by calling it directly:
do_check()
I don't know what your get_next function does, so I don't know if you need to call it periodically too. Probably not. I'm guessing it waits for the next button press, which you don't need to do with tkinter or most other GUI toolkits. Instead, you configure the button to call a function when clicked.
Regardless, the way to do the type of looping you want is to place events on the event queue at a regular interval.