Siyu Siyu - 1 year ago 80
Python Question

return value from a event-binded function

I'm trying to write a function which can wait for me to press anykey and then return my mouse position. I'm confused about how to get my xy value from key(event) function and return them with get_mouse_pixel().

from Tkinter import *
import win32api

def get_mouse_pixel():
x,y = 0,0

root = Tk()

def key(event):
x,y = win32api.GetCursorPos()
print "pressed", repr(event.char)
print "mouse position", x, y

def callback(event):
print "clicked at", event.x, event.y

frame = Frame(root, width=0, height=0)
frame.bind("<Key>", key)
frame.bind("<Button-1>", callback)


print x,y
return x,y


Answer Source

Since you're using inner functions and you give them values, you have to tell your inner function (key()) that the x and y you're setting aren't new variables, they're the ones in the outer scope. You can do that with the nonlocal keyword in python3 (eg nonlocal x,y x,y = win32api.GetCursorPos()), or global in python2. If you didn't assign to them, you could read from them in the inner scope, but you can't re-assign to them.

A different way to do it is that you can modify nonlocal variables. I.e. you can change mutable data types that aren't local- if you change x and y into a dictionary d = {'x':0, 'y':0}, your key() can change that nonlocal;

# Define x/y as dictionary d higher
def key(event):
    d['x'],d['y'] = win32api.GetCursorPos()
    # Everything else you would like to do with x/y.

This will change dictionary d to hold the new values without having to do potentially destructive things with global variables with the immensely common names x and y.

With the dict method, you can either return the whole dictionary or you can return each piece (ie return d['x'], d['y']) to return nice ints if you want.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download