【问题标题】:embedding a matplotlib graph in a Tkinter canvas widget class在 Tkinter 画布小部件类中嵌入 matplotlib 图
【发布时间】:2015-02-17 06:02:51
【问题描述】:

我正在尝试创建一个在画布对象中嵌入 matplotlib 图形的 Tkinter 小部件类。我编写的代码几乎可以工作,但在小部件关闭时似乎无法正常退出。这是我正在使用的代码。这不是我正在使用的实际 matplotlib 图形代码,而是我为了问这个问题而写的。我最初的 matplotlib 图形代码很长,无法尝试复制这篇文章。

from Tkinter import *
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import matplotlib.pyplot as plt

def schart2(stock_sym):
    x = [1,2,3,4]
    y = [20,21,20.5, 20.8]
    plt.plot(x,y)
    plt.show()

class StockChart(Frame):
    def __init__(self, stock_sym=''):
        Frame.__init__(self, parent=None)
        self.pack(expand=YES, fill=BOTH)
        self.makeWidgets(stock_sym)

    def makeWidgets(self, stock_sym):
        #self.f = graphData(stock_sym,12,26)
        self.f = schart2(stock_sym)
        self.canvas = FigureCanvasTkAgg(self.f)
        self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
        self.canvas.show()



if __name__ == '__main__':
    StockChart('ACAD').mainloop()

当我运行此代码时,小部件已正确绘制并按预期运行,但当我单击关闭图标按钮时,小部件从屏幕上消失,但代码继续运行,空闲提示不再出现,而只是空闲提示有一个闪烁的光标但没有提示。通常,当我创建这样的小部件时,当我单击关闭图标按钮时,小部件会关闭,并且底层代码也会退出,使我返回到正常的空闲提示。如果有人对如何让此代码正确退出有任何想法,我将不胜感激。我假设问题与执行 matplotlib 嵌入的代码部分有关。此致,乔治

【问题讨论】:

  • 可能是因为您已经替换了实际的图形代码,所以此代码根本无法运行(请注意您的命名空间问题以及 schart2 不返回数字等事实) - 请修复这样想要帮助您调试的人实际上可以。
  • 感谢您的回复,但此代码运行良好。当我运行这个我发布的确切代码时,一切都完全按照我的描述工作。此致,乔治
  • 你得到一个数字,但你也得到:AttributeError: 'NoneType' object has no attribute 'set_canvas'来自FigureCanvasAgg.__init__。因为,正如我所说, chart2 不返回数字。请注意您的错误消息。
  • 感谢您的回复。运行此代码时,我没有收到任何错误消息。当我运行此代码时,我得到的图表没有错误消息。当我退出图形时,我在空闲窗口中看到一个闪烁的光标,但没有空闲提示,也没有错误消息。如果我只运行 schart2 本身会返回一个图形(我的代码指定的图表已绘制),当我关闭此图形时,代码完成并返回到预期的空闲提示。
  • 如果“matplotlib.use('TkAgg')”语句未包含在代码的导入部分中,则会出现您描述的错误消息。据我了解,如果不包含“matplotlib.use('TkAgg')”语句,则代码的“self.canvas = FigureCanvasTkAgg(self.f)”部分将不起作用。此致,乔治

标签: python canvas matplotlib embed


【解决方案1】:

您根本没有使用此代码访问 Tkinter,因为您的函数 schart2 返回 None,然后将其分配给 self.f 并用于 self.canvas = FigureCanvasTkAgg(self.f)

相反,您获得的窗口来自 Matplotlib - plt.plotplt.show 命令会弹出一个纯 matplotlib 图。

要以您想要的方式在 Tkinter 中获得嵌入式图形,您所要做的就是重新执行 schart2 以返回一个图形,并且不要使用 pyplot:

def schart2(stock_sym):
    x = [1,2,3,4]
    y = [20,21,20.5, 20.8]
    fig = Figure()
    axes = fig.add_subplot(111)
    axes.plot(x,y)
    return fig

另外:

您还需要删除self.canvas.show(),因为它会导致关于“update_idletasks”属性的 Tkinter 错误,但我不足以让 Tkinter 专家解决这个问题,而且这是一个单独的问题(已经有一些关于 SO 的讨论)。还有一个命名空间问题——把Tk.side=Tk.TOP, fill=Tk.BOTH中去掉,因为你已经完成了from Tkinter import *

【讨论】:

  • 您好,非常感谢您的回复。我进行了您建议的所有更改,它消除了 matplotlib 图形未正确关闭的问题,但它确实带来了另一条错误消息。这是我收到的错误消息:Tkinter 回调 Traceback 中的异常(最近一次调用最后一次):... AttributeError: 'NoneType' object has no attribute 'update_idletasks'
  • 我最大的问题是主要修复的是图形代码而不是 Tkinter 代码,因为我在这篇文章中使用的图形代码是简化的图形代码,而不是我将拥有的实际图形代码弄清楚如何对我的实际图形代码进行必要的调整。再次感谢你的帮助。此致,乔治
  • 嗯,这就是导致您描述的行为的原因。另一个错误是无关的。尝试查看有关该主题的各种问题,看看他们是否回答了该问题。
猜你喜欢
  • 1970-01-01
  • 2013-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-07
  • 1970-01-01
  • 2017-06-30
相关资源
最近更新 更多