首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么matplotlib.figure.Figure的行为与matplotlib.pyplot.figure如此不同?

为什么matplotlib.figure.Figure的行为与matplotlib.pyplot.figure如此不同?
EN

Stack Overflow用户
提问于 2015-07-24 12:59:32
回答 1查看 745关注 0票数 3

一位程序员同事提醒我注意一个问题,matplotlib.pyplot和Tkinter在一起的表现不太好,Tkinter/Matplotlib后端冲突导致无限主循环的问题就证明了这一点。

我们更改了代码,以防止链接问题中提到的潜在问题,如下所示:

代码语言:javascript
运行
复制
import matplotlib.pyplot as plt
self.fig = plt.figure(figsize=(8,6))
if os.path.isfile('./UI.png'):
    image = plt.imread('./UI.png')
    plt.axis('off')
    plt.tight_layout()
    im = plt.imshow(image)
# The Canvas
self.canvas = FigureCanvasTkAgg(self.fig, master = master)
self.toolbar = NavigationToolbar2TkAgg(self.canvas, root)
self.canvas.get_tk_widget().pack(fill=BOTH,expand=YES)
self.canvas.draw()

中间层(未显示UI.png)

代码语言:javascript
运行
复制
import matplotlib.pyplot as plt
import matplotlib
self.fig = matplotlib.figure.Figure(figsize=(8, 6))
if os.path.isfile('./UI.png'):
    image = matplotlib.image.imread('./UI.png')
    plt.axis('off')
    plt.tight_layout()
    plt.imshow(image)
# The Canvas
self.canvas = FigureCanvasTkAgg(self.fig, master=master)
self.toolbar = NavigationToolbar2TkAgg(self.canvas, root)
self.canvas.get_tk_widget().pack(fill=BOTH, expand=YES)
self.canvas.draw()

更改后的代码不再显示“背景”图像,而且我一直在尝试一些随机的东西(因为我对这两个选项之间的差异非常困惑),以使图形再次显示。这些更改涉及从tight_layout切换到set_tight_layout以避免警告,就像https://github.com/matplotlib/matplotlib/issues/1852上提到的那样。由此产生的代码如下:

势固定

代码语言:javascript
运行
复制
import matplotlib.pyplot as plt
import matplotlib
self.fig = matplotlib.figure.Figure(figsize=(8, 6))
background_image = self.fig.add_subplot(111)
if os.path.isfile('./UI.png'):
    image = matplotlib.image.imread('./UI.png')
    background_image.axis('off')
    #self.fig.tight_layout() # This throws a warning and falls back to Agg renderer, 'avoided' by using the line below this one.
    self.fig.set_tight_layout(True)
    background_image.imshow(image)
# The Canvas
self.canvas = FigureCanvasTkAgg(self.fig, master=master)
self.toolbar = NavigationToolbar2TkAgg(self.canvas, root)
self.canvas.get_tk_widget().pack(fill=BOTH, expand=YES)
self.canvas.draw()

因此,问题是,为什么我们现在需要使用一个子图(使用matplotlib.figure.Figure),而之前我们没有使用(使用matplotlib.pyplot)?

PS:我很抱歉,如果这是一个愚蠢的问题,但几乎所有我能找到的主题似乎使用了matplotlib.pyplot变体。因此,我很难为matplotlib.figure.Figure变体找到任何好的文档。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-27 11:00:57

TL;DR

因此,问题是,为什么我们现在需要使用一个子图(使用matplotlib.figure.Figure),而之前我们没有使用(使用matplotlib.pyplot)?

subplot创建一个Axes对象。你以前也有过,但是pyplot API“隐藏”了它,所以你没有意识到这一点。您现在正在尝试直接使用对象,所以必须自己处理。

更详细的理由

您之所以看到这种行为是因为matplotlib.pyplot是如何工作的。引用一下本教程的话:

matplotlib.pyplot是命令样式函数的集合,它使matplotlib像MATLAB一样工作.matplotlib.pyplot是有状态的,它跟踪当前图形和绘图区域,并将绘图功能定向到当前轴。

关键的一点是pyplot是有状态的。它跟踪状态“隐藏”,并在一定程度上向您隐藏对象模型。它也做了一些隐含的事情。因此-如果您只是简单地调用,例如,plt.axis(),在封面下调用plt.gca(),然后调用gcf(),这将是返回一个新数字,因为您还没有通过pyplot设置一个数字。对于大多数对plt.some_function()的调用来说,这都是正确的--如果pyplot在它自己的状态中没有一个图形对象,它将创建一个。

因此,在您的中间示例中,您已经创建了自己的Figure对象--将其命名为self.fig (我不确定您的类结构是什么,所以我不知道self是什么,但我猜它是您的tk.Frame对象或类似的东西)。

这句话

pyplot 对一无所知因此,在中间代码中,在处于imshow()状态的Figure对象上调用pyplot,但在画布上显示一个不同的图形(self.fig)。

问题不在于您需要使用subplot本身,而是需要更改正确的Figure对象上的背景图像。在您的潜在修复代码中使用subplot的方式会做到这一点--尽管我在下面建议了一种替代方法,这可能会使意图更加清晰。

如何修复

变化

代码语言:javascript
运行
复制
plt.axis('off')
plt.tight_layout()
plt.imshow(image)

代码语言:javascript
运行
复制
self.fig.set_tight_layout(True)
ax = self.fig.gca() # You could use subplot here to get an Axes object instead
ax.axis('off')
ax.imshow(image)

关于根本原因的说明:pyplot API与直接使用对象

这是个小小的意见,但可能会有帮助。当我需要快速获得原型并希望使用一个相当标准的情况时,我倾向于使用pyplot接口。通常,这就足够了。

当我需要做更复杂的事情时,我就开始直接使用对象模型--维护我自己的名为FigureAxes对象等等。

混合两者是可能的,但往往令人困惑。你在中间解决方案中找到了这个。所以我建议你做一个或另一个。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31611188

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档