【问题标题】:Using Matplotlib with tkinter (TkAgg)将 Matplotlib 与 tkinter (TkAgg) 一起使用
【发布时间】:2016-06-20 04:33:29
【问题描述】:

我在使用 tkinter 运行 Matplotlib 时一直遇到问题。我的代码和其他代码都会出现这种情况,包括我从网上下载的示例代码,这些代码可能适用于其他人。

matplotlib.use('TkAgg') 的初始用户警告发生在我使用 IPython 控制台而不是标准 Python 控制台时。我认为这只是意味着 IPython 更加冗长,因为无论哪种情况,程序都会在 canvas.show() 上崩溃。我一直在尝试运行的完整代码来自 Matplotlib 网站:

#!/usr/bin/env python

import matplotlib
matplotlib.use('TkAgg')

from numpy import arange, sin, pi
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
# Implement the default mpl key bindings
from matplotlib.backend_bases import key_press_handler


from matplotlib.figure import Figure

import sys
if sys.version_info[0] < 3:
    import Tkinter as Tk
else:
    import tkinter as Tk

root = Tk.Tk()
root.wm_title("Embedding in TK")


f = Figure(figsize=(5, 4), dpi=100)
a = f.add_subplot(111)
t = arange(0.0, 3.0, 0.01)
s = sin(2*pi*t)

a.plot(t, s)


# A tk.DrawingArea
canvas = FigureCanvasTkAgg(f, master=root)
canvas.show()
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

toolbar = NavigationToolbar2TkAgg(canvas, root)
toolbar.update()
canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)


def on_key_event(event):
    print('you pressed %s' % event.key)
    key_press_handler(event, canvas, toolbar)

canvas.mpl_connect('key_press_event', on_key_event)


def _quit():
    root.quit()     # Stops mainloop
    root.destroy()  # This is necessary on Windows to prevent
                    # Fatal Python Error: PyEval_RestoreThread: NULL tstate

button = Tk.Button(master=root, text='Quit', command=_quit)
button.pack(side=Tk.BOTTOM)

Tk.mainloop()
# If you put root.destroy() here, it will cause an error if
# the window is closed with the window manager.

使用调试器,我跟随 canvas.show 进入 tkinter (backend_tkagg.py):

def draw(self):
    FigureCanvasAgg.draw(self)
    tkagg.blit(self._tkphoto, self.renderer._renderer, colormode=2)
    self._master.update_idletasks()

我跳过 FigureCanvasAgg.draw ok 并进入 tkagg.blit...注意传递给 tkagg.blit 的数据都不是应用程序数据。此调用将我带到 tkagg.py,即:

def blit(photoimage, aggimage, bbox=None, colormode=1):
    tk = photoimage.tk

    if bbox is not None:
        bbox_array = bbox.__array__()
    else:
        bbox_array = None
    data = np.asarray(aggimage)
    try:
        tk.call("PyAggImagePhoto", photoimage,
            id(data), colormode, id(bbox_array))
    except Tk.TclError:
        try:
            try:
                _tkagg.tkinit(tk.interpaddr(), 1)
            except AttributeError:
                _tkagg.tkinit(id(tk), 0)
            tk.call("PyAggImagePhoto", photoimage,
                    id(data), colormode, id(bbox_array))
        except (ImportError, AttributeError, Tk.TclError):
            raise

它在 tk.call 上反复失败,我认为这是对 Tcl 的调用。

我在此处修改了代码以将 TclError 作为变量捕获,以便我可以在调试器中对其进行检查。它说:tclErr: invalid command name "PyAggImagePhoto"

我怎么看这个?

【问题讨论】:

  • 你能提供一个最小的例子吗?我的猜测是您正在使用带有--pylab 的ipython? ?
  • 我正在使用 ipython 但没有指定 --pylab。但是我在标准 python 控制台中尝试过,并没有收到用户警告。然而,他们都在调用 canvas.show 时崩溃了。顺便说一句,我正在使用 tkinter 8.6。在调试器中,我发现它是 tkagg.py 中的内部调用,是从 backend_tkagg.py 使用它自己的内部数据调用的,而不是我的。它在尝试显示其位图时调用 tcl 失败,即在两种情况下都调用 blit 方法......后端版本调用调用 tcl 的 tkagg 版本
  • 能否请您发布实际运行代码?请阅读How to create a Minimal, Complete and Verifiable Example
  • 我已经添加了完整的代码......这是matplotlib网站的一个例子。
  • 这是 Anaconda 3 发行版的一个问题...请参阅 groups.google.com/a/continuum.io/forum/#!topic/anaconda/… 以获得完整的讨论。简短的回答是不要使用 TkAgg 使用默认的 QtAgg 和 matplotlib.pyplot。

标签: python matplotlib tkinter anaconda


【解决方案1】:

替换后,此代码对我有用

NavigationToolbar2TkAgg

NavigationToolbar2Tk

也换了

canvas.show()

canvas.draw()

注意,我使用 Anaconda 4.8.3、Matplotlib 3.2.1、Tkinter 8.6 和 Windows 10。

【讨论】:

    【解决方案2】:

    总结一下:

    【讨论】:

    猜你喜欢
    • 2020-07-17
    • 1970-01-01
    • 2022-08-06
    • 2015-11-27
    • 2020-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多