Reputation: 187
So simply put I want my code to call a event like OnKeyPress("Keyname") or something, each time I press a key. I don't want to use tkinter.
I have a Update method that gets called 20 times a second that's in a parent class I have several child classes that have that function called. On some of them I want to use a key press event to make parts of my robot I am working on move.(eg: while I am pressing the up arrow the robot will move foreword) tkinter is well not designed for this its more for drawing content on a screen and I want to make my code more efficient for its purpous. also I would prefer to have my own then use a pre-made one so I can get a better understanding on how it works.
Upvotes: 0
Views: 1208
Reputation: 19144
I urge you to reconsider not using tkinter. Ignoring the GUI stuff, it has a tested, cross-platform, asynchonous event loop system that handles both scheduled (timed) events and key press and release events. And it is written in C and updated as platforms change. (See the comments for the recipe @Ty quoted about platform changes.) You will find it very difficult to reproduce the same facilities in Python.
Usage would start with
import tkinter
root = tkinter.Tk()
root.withdraw() # make the window invisible
Thereafter, one can ignore the GUI stuff and only use root.bind(key event, function) and root.after(milleseconds, function, *args). (In the meanwhile, the option to use graphics to interact with the robot, in the future, would still be there.)
Given existing move_forward and stop_move functions, here is how to make a robot move while pressing up-arrow.
root.bind('<KeyPress-Up>', move_forward)
root.bind('<keyRelease-Up>' stop_move)
About the importance of being asynchronous (non-blocking): I presume you call an update function 20 times a second by calling time.sleep(.05) between each update. This is a blocking call and during this period your code is frozen. It cannot do anything and cannot respond to events.
Suppose you develop two or more animations for the robot: say one for the arms, one for the head (or whatever is appropriate for your robot). Each would consist of a series times commands, implemented by root.after calls. Now suppose you want to run two or more animations in parallel. Assuming that each only requires a small fraction of CPU time, this would be trivial with tkinter because each would run asynchronously and not block the program from doing other things. With a blocking event system, you would have to write a new animation each each combination you want.
Upvotes: 1
Reputation: 115
This should work
class _GetchUnix:
def init(self):
import tty, sys
def call(self):
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
class _GetchWindows:
def init(self):
import msvcrt
def call(self):
import msvcrt
return msvcrt.getch()
class _Getch:
def init(self):
try:
self.impl = _GetchWindows()
except ImportError:
self.impl = _GetchUnix()
def __call__(self): return self.impl()
getch = _Getch()
while True:
if getch.impl():
print getch.impl()
Every thing up to the while
loop you need. Then when ever you call getch.impl()
it will wait for a input, but if there is none, it will move on. That's why I used the while
loop
DISCLAIMER
This is not my code, please check out:
http://code.activestate.com/recipes/134892/
Upvotes: 0