在tk应用程序内触发close事件后,matplotlib图无法继续执行程序流 [英] matplotlib figure does not continue program flow after close event triggered inside tk app

查看:199
本文介绍了在tk应用程序内触发close事件后,matplotlib图无法继续执行程序流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Windows和Mac处理python tk窗口和matplotlib图close_event的方式之间遇到了一个非常烦人的区别.

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

因此,我的问题是

  1. 我正在尝试从tk按钮事件中加载matplotlib图.
  2. 我希望显示该图,并阻止tk UI程序流,同时 该图处于活动状态,并捕获用户事件,直到该图处于 已关闭.
  3. 地块关闭后,tk应用程序应继续.
  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()

遗憾的是,我发现这在Windows中可以按预期工作,但在使用相同版本的python2.7,matplotlib(1.5.2)的mac上无法正常工作. 除了这不是良好的UI惯例之外,这令我感到困扰的是,这段代码在Mac和Windows上有所不同.我将不胜感激任何对此问题有帮助的反馈,同时,我将开始在不阻塞的线程上实施绘图仪,并在关闭时将结果传回主应用程序.

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.

推荐答案

您可以使用plt.ion()打开Matplotlib的交互模式,但这本身会使程序继续运行而不会阻塞流程.要手动阻止流,请使用self.fig.canvas.start_event_loop_default()self.fig.canvas.stop_event_loop()暂停程序流,直到捕获事件为止.

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()

这篇关于在tk应用程序内触发close事件后,matplotlib图无法继续执行程序流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆