Python - Check for keypresses without using 100% cpu
You want to catch key events, instead of polling for the current keyboard state.
See Events and Bindings in the TkInter docs, which has a simple example that does exactly what you want (plus, it's cross-platform instead of Win32-only).
And this is generally an issue with all GUI programming (and network servers, for that matter), and the answer is always the same. You don't directly use non-blocking "check for current X status" calls usefully, with or without threads. In the main thread, you ask the event loop "call my function when X status changes", or you create a background thread and make a blocking "wait forever until X happens" call.
The Wikipedia page on Event loop actually has a pretty good description of this.
Looking at your edited version, you've got a completely new problem now:
class Application(Frame): def __init__(self, master=None): Frame.__init__(self, master) self.pack() coords = StringVar() Label(master=self, textvariable=coords).pack() def GetCoords(): coords.set(str(win32api.GetCursorPos())) root.bind_all("<Scroll_Lock>", self.GetCoords)
GetCoords
is a local function defined inside Application.__init__
. But you're trying to use it as if it were a method of Application
. You can't do self.GetCoords
unless GetCoords
is a method of self
. That's exactly what the error message AttributeError: Application instance has no attribute 'GetCoords'
means.
But you can just pass the local function GetCoords
, just by taking out the self.
prefix. I'm not sure this will do what you think (because I'm not sure whether you can close over a StringVar
like that or not), but… try it and see.
Alternatively, you can make GetCoords
a method just by moving it out of the def __init__
and giving it a self
parameter. Then you can access self.GetCoords
, and get a bound method, which you can pass exactly as you're trying to. However, in that case, it won't be able to access coords
anymore, since that's a local variable inside __init__
. To fix that, change that local variable into a member variable, by using self.coords
everywhere in __init__
and GetCoords
(and anywhere else) instead of coords
.