在 tk 应用程序内部触发关闭事件后,matplotlib 图不继续程序流
matplotlib figure does not continue program flow after close event triggered inside tk app
我发现 windows 和 mac 如何处理 python tk window 和 matplotlib 图 close_event 之间的一个非常烦人的差异。
我的问题是,
- 我正在尝试从 tk 按钮事件加载 matplotlib 图。
- 我想显示图形,并阻止 tk UI 程序流,同时
该图处于活动状态,并捕获用户事件直到该图被激活
关闭。
- 情节关闭后,tk 应用程序应继续。
显示问题的最小示例应用程序。
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()
遗憾的是,我发现这在 windows 中按预期工作,但在 mac 上使用相同版本的 python2.7,matplotlib (1.5.2)。
除了这不是好的 UI 实践之外,令我困扰的是这段代码在 Mac 和 Windows 上存在差异。我将不胜感激任何有助于解决此问题的反馈,与此同时,我将开始在非阻塞线程上实现绘图仪,并在关闭时将结果传回主应用程序。
您可以使用plt.ion()
开启Matplotlib的交互模式,但这本身会导致程序继续运行而不会阻塞流程。要手动阻止流程,请使用 self.fig.canvas.start_event_loop_default()
和 self.fig.canvas.stop_event_loop()
暂停程序流程,直到事件被捕获。
在您的最小示例中实现:
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()
我发现 windows 和 mac 如何处理 python tk window 和 matplotlib 图 close_event 之间的一个非常烦人的差异。
我的问题是,
- 我正在尝试从 tk 按钮事件加载 matplotlib 图。
- 我想显示图形,并阻止 tk UI 程序流,同时 该图处于活动状态,并捕获用户事件直到该图被激活 关闭。
- 情节关闭后,tk 应用程序应继续。
显示问题的最小示例应用程序。
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()
遗憾的是,我发现这在 windows 中按预期工作,但在 mac 上使用相同版本的 python2.7,matplotlib (1.5.2)。 除了这不是好的 UI 实践之外,令我困扰的是这段代码在 Mac 和 Windows 上存在差异。我将不胜感激任何有助于解决此问题的反馈,与此同时,我将开始在非阻塞线程上实现绘图仪,并在关闭时将结果传回主应用程序。
您可以使用plt.ion()
开启Matplotlib的交互模式,但这本身会导致程序继续运行而不会阻塞流程。要手动阻止流程,请使用 self.fig.canvas.start_event_loop_default()
和 self.fig.canvas.stop_event_loop()
暂停程序流程,直到事件被捕获。
在您的最小示例中实现:
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()