Time.sleep in Kivy - python

I am looking for some thing like time.sleep in Kivy, because kivy does not support time.sleep and it hangs when i run a program using time.sleep.
I searched and found a function called:
Clock.schedule_interval(self.callback, interval)
but its not probably like time.sleep. Clock.schedule calls a function every x seconds, but I want to make a delay.
kivy.clock

kivy does not support time.sleep
Kivy supports time.sleep just fine, it just doesn't do what you want it to do - as per the function name, it sleeps, which means kivy 'freezes' as it isn't taking input, updating the graphics etc.
Anyway, it sounds like you want Clock.schedule_once(function, time). That will call the function (with a default argument dt) in time seconds.

Related

appJar status bar doesn't update in real time

I've set up a simple appJar UI, which has an "execute" button that calls a function containing code that takes a minute to run. I have injected my gui() variable, app, into this function.
There are 4 major steps, after each of which I would like a Statusbar to update to reflect that a step has been completed. However, what tends to happen is that as the function code runs, the GUI becomes unresponsive and it isn't until the code completes execution that ALL of the changes to the status bar are displayed at once.
My question is how should I be handling the UI such that the Statusbar is updated in real time?
appJar is just a wrapper around python tkinter module from standard library.
While your code is running, the ui is not running, thus it becomes unresponsive. If you want the ui to remain responsible, you have to return control from your code to the ui library from time to time.
That can be done by calling gui.topLevel.update() in your code, or by using asynchronous programming and having the main async loop call it, or by using threads.
Which one of those is the best, depends on what your program is doing.
appJar also has built in support for threads: http://appjar.info/pythonThreads/
You can call the function that takes a long time in a thread: app.thread(myFunction, param1, param2)
And, if you want to get the thread to update the GUI, you'll need to use the update queue: app.queueFunction(app.setMeter, "myMeter", 50)

Python's Tkinter after() function jumps CPU

I'm building a Python GUI app using tkinter.
Basically I'm starting and integrating with a different thread, while communication goes using input and output queues.
In the GUI side (the main thread where tkinter's mainloop() goes) I want to add a function which will be called on every iteration of the mainloop (I'm processing and displaying information on real-time).
So my function does something like that:
def loop(self):
try:
output_type, data = wlbt.output_q.get_nowait()
pass # if got something out of the queue, display it!
except Queue.Empty:
pass
self.loop_id = self.after(1, self.loop)
While when starting the program I just call self.loop_id = self.after(1, self.loop).
So two things that bother me:
The loop function raise the CPU usage by 30%-50%. If I disable it then it's good.
I want to be able to use after_idle() to maximize the refresh-rate, but I wasn't able to just replace it - got and error.
I'm sensing there's something I don't fully understand. What can be done to address these issues?
When you call self.after(1, self.loop) you are asking for a function to be run roughly once per millisecond. It's not at all surprising that the CPU usage goes up since you are making 1000 function calls per second.
Given that humans cannot perceive that many changes, if all you're doing is updating the display then there's no reason to do that more than 20-30 times per second.

Python : Timer without blocking the window in Tkinter

For a project I need to do, I code a Bomberman.
I'm working with the software Pyzo, in Python language, and with Tkinter.
The problem I have is that I need to a timer for the bomb, for example, I put a bomb and it exploded 3 seconds after.
But I have tested with many different things like .after; time module (time.sleep), a loop.
The consequence is always the same, the windows freezes and I can't move anymore, but when the loop is finished, the screen is refreshed and players are at new positions.
How can I do a proper timer to permit my bombs to explode after 3 seconds ?
Thank you!
You can use
widget.after(milliseconds, function, *arguments)
to let the function(*arguments) be called after milliseconds. If the function takes no arguments use widget.after(milliseconds, function). One argument widget.after(milliseconds, function, arg1), ....
widget can be Tk(), Canvas(), Frame(), Label(), ... object.
If you are interested in loops: tkinter loop and serial write

How to have a PyQT program keep refreshing one widget, always providing an up-to-date value?

I'm learning to program with PyQT4 and Python. I'm trying to code a simple app that will display the current CPU usage in a QLCD widget. For CPU usage I'm using psutils module.
The problem is that the CPU usage is not updated all the time - it only records the CPU usage at the moment the app has been launched (I'm guessing), and then it just stops. So, I'm looking for some sort of a loop equivalent that will hopefully not take too much of CPU power to process.
This is what I have so far:
self.wpCpuUsage.display(cpu_percent(interval=1))
and this is within __init__ of the QMainWindow class.
I've tried putting it in a for loop, but then it iterates over it, and basically waits for it to iterate and then executes the program.
Help?
You can use a QTimer[reference] object with a callback.
Something like that should work:
def call_this():
self.wpCpuUsage.display(cpu_percent(interval=1))
self.my_timer = QtCore.QTimer()
self.my_timer.timeout.connect(call_this)
self.my_timer.start(1000) #1 second interval

Tkinter after that survives clock rewinding

I noticed that in my version of Tkinter, the after() call does not survive system clock rewinding.
If the after(x, func) was called, and the system clock was rewinded, func will be called only after the clock returned to its time before the rewind + x milliseconds.
I assume this is because Tkinter uses the system-clock instead of the "time.clock" (the amount of time that the program is running).
I tested it only on windows, and maybe its because I have an old version of Tkinter.
I want my App to work on computers that synchronize their clock from the network...
Does anyone have a simple solution?
Unfortunately, neither Tkinter nor Tcl interpreter have an straightforward solution to your problem. The after(ms, func) method is based on the Tcl command of the same name, which creates an internal timer based on the current system time plus the amount of milliseconds passed as parameter.
In case you are curious, you can check it out directly from the Tcl/Tk source code:
Tcl_GetTime(&wakeup);
wakeup.sec += (long)(ms / 1000);
wakeup.usec += ((long)(ms % 1000)) * 1000;
if (wakeup.usec > 1000000) {
wakeup.sec++;
wakeup.usec -= 1000000;
}
afterPtr->token = TclCreateAbsoluteTimerHandler(&wakeup,
AfterProc, afterPtr);
Given this limitation, I would go for a pure Python approach, like using a Timer:
import time
import threading
import tkinter as tk
root = tk.Tk()
def say_hi():
print(time.perf_counter(), "-", "Hi after 30sec!")
root.destroy()
print(time.perf_counter(), "-", "Waiting 30sec")
threading.Timer(30, say_hi).start()
root.mainloop()
It also has the advantage that runs on a separate thread, preventing not only blocking the GUI during the timer interval but also while executing the callback function.
Explanation
As you suspected, when you use .after() tkinter is scheduling an event to happen at current_time + delay_ms. This means that if system time changes between those events, it will subvert the scheduled event.
This is based on the fact that tkinter is simply calling the after command of tcl (the underlying system that tkinter is communicating to). tcl docs tell us:
after uses the system time to determine when it is time to perform a scheduled event. This means that with the exception of after 0 and after idle, it can be subverted by changes in the system time.
Now notice that after idle is exempt from the system clock coupling as well as after 0 but those probably aren't good replacements for you.
after 0
This schedules a script for immediate execution. It's useful for getting the tightest possible event. Warning: This places the scheduled event at the front of the queue, so a command that perpeually reschedules itself in this manner can lock up the queue.
So using after 0 would not be optimal as it is in the front of the event queue meaning nothing else would happen.
after idle
This is similarly exempt but it probably won't be best either. [docs]
The script will be run exactly once, the next time the event loop is entered and there are no events to process.
So the script would run when the system next becomes idle. You could use after x with after idle and that would wait until the events are clear and the system is idle, then wait x milliseconds before running that command but I suspect that isn't what you want to do either.
Tl;dr
So to your final question, what can you do if the clock could be expected to be reversed? Native to tkinter: not much. Unless you caught the reverse happening and reset your after() event or writing your own event scheduler based on time.process_time() (formerly time.clock()), I don't see a way to have .after() perform differently.

Categories