Search code examples
pythonpython-3.xvariablesscopepynput

Why is the mouse position that is stored in the function not changed outside the function?


I'm currently working on a chessboard project in python. I need to store the mouse position when it is pressed, to see if the (x, y) coordinates touch a piece.

If it does, the piece's coordinates will be the same as the mouse's coordinates, until there's mouse release. I want to create the effect that piece is following the mouse.

Then, when it is released, I want to store the coodinates of where it was released to work with these. I heard about pynput and installed it, but I'm still new to it.

This is not in my main file, but it's an attempt of getting the position of the mouse when clicked:

from pynput import mouse


mx, my = 0, 0


def on_click(x, y, button, pressed):
    print('{0} at {1}'.format(
        'Pressed' if pressed else 'Released',
    (x, y)))
    mx = x
    my = y
    if not pressed:
        # Stop listener
        return False


with mouse.Listener(
        on_click=on_click) as listener:
    listener.join()

print(str(mx) + str(my))

I don't really understand the logic behind this module. I found the code online and tried to store the values in variables, but it clearly doesn't work.


Solution

  • To store values in external variables you would have to use global

    But usually all code is executed inside on_click and then there is no need to use global


    from pynput import mouse
    
    pressed_x = 0
    pressed_y = 0
    
    released_x = 0
    released_y = 0
    
    is_pressed = False
    is_released = False
    
    def on_click(x, y, button, pressed):
        global pressed_x
        global pressed_y
    
        global released_x
        global released_y
    
        global is_pressed
        global is_released
    
        # store in external variables
        if pressed:
            is_pressed = True
            pressed_x = x
            pressed_y = y
            #print('LISTENER: pressed:', pressed_x, pressed_y)
        else:        
            is_released = True
            released_x = x
            released_y = y
            #print('LISTENER: released:', released_x, released_y)
    
        #if not pressed:
        #    # Stop listener
        #    return False
    
    # --- main ---
    
    # start listener at the beginning
    listener = mouse.Listener(on_click=on_click)
    listener.start()
    
    # use variables in your code
    while True:
        if is_pressed:
            print('RUN: pressed:', pressed_x, pressed_y)
            is_pressed = False
        if is_released:
            print('RUN: released:', released_x, released_y)
            is_released = False
    
    # stop listener at the end
    listener.stop()            
    listener.join()
    
    print('END: pressed:', pressed_x, pressed_y)
    print('END: released:', released_x, released_y)
    

    But if you use pygame, pyglet or any GUI framework (tkinter, PyQT, PySide, wxPython, PyGTK, Kivy, etc.) then they have own methods to get mouse position (bind(), signals, events, etc.) and there is no need to use pynput.