matplotlib figure does not continue program flow after close event triggered inside tk app

别等时光非礼了梦想. 提交于 2019-12-11 05:46:38

问题


I've come across a really annoying difference between how windows and mac handles a python tk window and matplotlib figure close_event.

My problem is thus,

  1. I am trying to load a matplotlib figure from a tk button event.
  2. I want the figure to show, and block the tk UI program flow while the plot is active, and capturing user events until the plot is closed.
  3. After the plot is closed the tk app should continue.

Minimal example app showing issue.

from Tkinter import *
from matplotlib import pyplot as plt


class Plotter:
    def __init__(self):
        self.fig = plt.figure()
        self.fig.canvas.mpl_connect('close_event', self.dispose)

        plt.plot(1, 2, 'r*')
        plt.show()
        print "done with plotter"

    def dispose(self, event):
        plt.close('all')
        print "disposed"


if __name__ == '__main__':
    def pressed():
        print 'button pressed'
        Plotter()
        print 'YAY'

    root = Tk()
    button = Button(root, text='Press', command=pressed)
    button.pack(pady=20, padx=20)

    root.mainloop()

Sadly, I found this works as expected in windows but not on mac using the same versions of python2.7, matplotlib (1.5.2). Apart from the fact that this is not good UI practice, it bothers me that there is a difference on Mac and Windows for this piece of code. I would appreciate any feedback that would help with this issue, in the mean time i'll start work on implementing the plotter on a thread which is non-blocking and passing the result back to the main app when closed.


回答1:


You can use plt.ion() to turn on Matplotlib's interactive mode, but this by itself will cause the program to continue without blocking the flow. To manually block the flow, use self.fig.canvas.start_event_loop_default() and self.fig.canvas.stop_event_loop() to pause the program flow until events are captured.

Implemented in your minimal example:

from Tkinter import *
from matplotlib import pyplot as plt

class Plotter:
    def __init__(self):
        plt.ion()
        self.fig = plt.figure()
        self.fig.canvas.mpl_connect('close_event', self.dispose)
        self.fig.canvas.mpl_connect('button_press_event', self.on_mouse_click)

        plt.plot(1, 2, 'r*')
        plt.show()
        self.fig.canvas.start_event_loop_default()
        print "done with plotter"

    def dispose(self, event):
        self.fig.canvas.stop_event_loop()
        print "disposed"

    def on_mouse_click(self, event):
        print 'mouse clicked!'


if __name__ == '__main__':
    def pressed():
        print 'button pressed'
        Plotter()
        print 'YAY'

root = Tk()
button = Button(root, text='Press', command=pressed)
button.pack(pady=20, padx=20)

root.mainloop()


来源:https://stackoverflow.com/questions/39130376/matplotlib-figure-does-not-continue-program-flow-after-close-event-triggered-ins

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!