Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

plot mouse movement Python

I would like to plot the movement of the mouse in near real-time using matplotlib and pynput, but I suspect I am getting some issues with the code being blocked. Code is uses a simplified version of this answer.

import matplotlib.pyplot as plt
from pynput import mouse
from time import sleep

fig, ax = plt.subplots()

ax.set_xlim(0, 1920-1)
ax.set_ylim(0, 1080-1)
plt.show(False)
plt.draw()

x,y = [0,0]
points = ax.plot(x, y, 'o')[0]
# cache the background
background = fig.canvas.copy_from_bbox(ax.bbox)

def on_move(x, y):
    points.set_data(x,y)
    # restore background
    fig.canvas.restore_region(background)
    # redraw just the points
    ax.draw_artist(points)
    # fill in the axes rectangle
    fig.canvas.blit(ax.bbox)

with mouse.Listener(on_move=on_move) as listener:
    sleep(10)

The code seems to halt on ax.draw_artist(points). The pynput mouse listener is a threading.Thread, and all callbacks are invoked from the thread. I am not familiar enough with the inner workings of matplotlib or threading to determine what is the cause.

like image 744
M.T Avatar asked May 24 '18 09:05

M.T


1 Answers

It might cause problems to run a thread with GUI input in parallel with the matplotlib GUI.
In any case, it could make more sense to use matplotlib tools only. There is an event handling mechanism available, which provides a "motion_notify_event" to be used to obtain the current mouse position. A callback registered for this event would then store the mouse position and blit the updated points.

import matplotlib.pyplot as plt


fig, ax = plt.subplots()

ax.set_xlim(0, 1920-1)
ax.set_ylim(0, 1080-1)

x,y = [0], [0]
# create empty plot
points, = ax.plot([], [], 'o')

# cache the background
background = fig.canvas.copy_from_bbox(ax.bbox)

def on_move(event):
    # append event's data to lists
    x.append(event.xdata)
    y.append(event.ydata)
    # update plot's data  
    points.set_data(x,y)
    # restore background
    fig.canvas.restore_region(background)
    # redraw just the points
    ax.draw_artist(points)
    # fill in the axes rectangle
    fig.canvas.blit(ax.bbox)


fig.canvas.mpl_connect("motion_notify_event", on_move)
plt.show()
like image 190
ImportanceOfBeingErnest Avatar answered Nov 04 '22 20:11

ImportanceOfBeingErnest