Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
Closed
Description
I have some code that continuously updates an MPL plot, and usedfig.canvas.start_event_loop(0.0001)
to listen for keyboard input. As of MPL 3.4, this code is broken in two ways:
- Commit c53570d converts the timeout to int milliseconds. This rounds down 0.0001 to 0 and fails to display the window at all. I might suggest
math.ceil(1000*timeout)
instead ofint(1000*timeout)
? - After changing 0.0001 to 0.001 in my code,Commit 630e806 causes MPL to throw an error
invalid command name "140668474408832stop_event_loop" while executing "140668474408832stop_event_loop" ("after" script)
when closing the window before pausing the loop. Expected behavior would be for it to simply terminate the loop. It's a harmless error in the minimal code below (you can still launch new runs), but my full code updates using anasyncio
event loop, which this behavior fails to exit, so this error prevents launching new runs in that case (asyncio.run() cannot be called from a running event loop
). Not sure how to fix this one, but I'll note that usingfig.canvas.flush_events()
in my code instead ofstart_event_loop
produces the desired behavior.
Not sure if#2 is worth fixing given thatflush_events()
restores the desired behavior, but@richardsheridan suggested I post an issue in my comment on that commit. Minimal example below. Launch an MPL window and then close it before pausing to trigger the error:
from random import randintimport matplotlib, matplotlib.pyplot as pltfrom tkinter import *class Visual:running = False#Construct a launch buttondef __init__(self):self.parent = Tk()self.runButton = Button(self.parent, text='Run', command=self.launchVisual, padx=10, pady=10)self.runButton.pack(fill="x", side=TOP)def start(self):self.runButton['text'] = 'Pause'self.runButton['command'] = self.stopself.running = Truewhile self.running:self.data.append(randint(0,100))self.line.set_ydata(self.data)self.line.set_xdata(range(len(self.data)))self.axes.relim()self.axes.autoscale_view(tight=False)if self.fig.stale: self.fig.canvas.draw_idle()#This rounds down to 0 and doesn't draw the window at all#self.fig.canvas.start_event_loop(0.0001)#This throws an error and breaks asyncio if you close the window before pausingself.fig.canvas.start_event_loop(0.001)#This works#self.fig.canvas.flush_events()def stop(self, *args):self.running = Falseself.runButton['text'] = 'Run'self.runButton['command'] = self.startdef terminate(self, evt=False):self.running = Falseself.runButton['text'] = 'New Model'self.runButton['command'] = self.launchVisualdef launchVisual(self):matplotlib.use('TkAgg')self.fig, self.axes = plt.subplots()self.fig.canvas.mpl_connect('close_event', self.terminate)#Keyboard inputdef pause(event):if event.key==' ' and event.canvas is self.fig.canvas:if self.running: self.stop()else: self.start()self.fig.canvas.mpl_connect('key_press_event', pause)self.data = []self.line, = self.axes.plot(self.data, color='#330099')self.fig.canvas.draw_idle()plt.show(block=False)self.start()viz = Visual()viz.parent.mainloop()