Soarder
Soarder

Reputation: 13

Matplotlib event handling without use of `show()`

I am attempting to use Matplotlib as a frontend for a simulator project. The simulator should take input from the user and update figures accordingly. Updating the figures in maptlotlib in real-time works fine, but there is no callbacks for events unless show() is called.

from time import sleep

import matplotlib.pyplot as plt

plt.figure()

def onclick(event):
    print 'button=%d, x=%d, y=%d, xdata=%f, ydata=%f'%(
    event.button, event.x, event.y, event.xdata, event.ydata)

plt.gcf().canvas.mpl_connect('button_press_event', onclick)

plt.plot([0,1,2],[5,10,15])

plt.show()

This code works and outputs events as per http://matplotlib.org/users/event_handling.html

Unfortunately I need to be able to do processing inbetween updates and cannot surrender control to show(). Changing from blocking show():

plt.show()

To non-blocking show(block=False) does not work:

plt.show(block=False)

#Running simulator, but not unable to receive events.
for i in xrange(10):
    print "Working %s" %i
    sleep(1)

I assume that this is related to the lack of a main loop doing event handling. I have found no information on how to do this manually.

Upvotes: 1

Views: 781

Answers (1)

Martin Evans
Martin Evans

Reputation: 46779

Depending on the job you need to perform, you could use Matplotlib to add an animation as follows, which would call a function repeatedly at a regular interval:

import matplotlib.pyplot as plt
import matplotlib.animation as animation


def one_second(event):
    global count
    count += 1
    print "Working %s" % count

def onclick(event):
    print 'button=%d, x=%d, y=%d, xdata=%f, ydata=%f'%(
    event.button, event.x, event.y, event.xdata, event.ydata)

count = 0
fig = plt.figure()
fig.canvas.mpl_connect('button_press_event', onclick)
plt.plot([0,1,2],[5,10,15])
ani = animation.FuncAnimation(fig, one_second, repeat=True, interval=1000)
plt.show()            

This would then print something like:

Working 1
Working 2
Working 3
Working 4
Working 5
Working 6
button=1, x=317, y=181, xdata=0.932120, ydata=8.018293
Working 7
button=1, x=388, y=233, xdata=1.213141, ydata=9.603659
button=1, x=273, y=285, xdata=0.757966, ydata=11.189024
Working 8

Alternatively, you could try the following approach using plt.pause():

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import time


def onclick(event):
    print 'button=%d, x=%d, y=%d, xdata=%f, ydata=%f'%(
    event.button, event.x, event.y, event.xdata, event.ydata)

fig = plt.figure()
fig.canvas.mpl_connect('button_press_event', onclick)
plt.plot([0, 1, 2], [5, 10, 15])

plt.ion()
plt.show()
count = 0
next = 0

while plt.fignum_exists(fig.number):
    print "Working %s" % count

    while time.time() < next:
        plt.pause(.001) 

    next = time.time() + 1.0  
    count += 1

Upvotes: 1

Related Questions