gpt4 book ai didi

python - 为什么 matplotlib.figure.Figure 的行为与 matplotlib.pyplot.figure 如此不同

转载 作者:行者123 更新时间:2023-11-28 17:34:45 30 4
gpt4 key购买 nike

一位程序员提醒我注意一个问题,matplotlib.pyplot 和 Tkinter 不能很好地协同工作,如这个问题所示 Tkinter/Matplotlib backend conflict causes infinite mainloop

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

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)

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 中所述。 .结果代码如下:

潜在修复

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 变体找到任何好的文档。

最佳答案

长话短说

The question therefore is, why do we need to use a subplot now (using matplotlib.figure.Figure) while before we did not (using matplotlib.pyplot)?

subplot 创建一个 Axes 对象。您之前确实有一个,但是 pyplot API 将它“隐藏”在幕后,所以您没有意识到。您现在正在尝试直接使用对象,所以必须自己处理。

更详细的原因

您看到此行为的原因是 matplotlib.pyplot 的工作方式。引用the tutorial一点点:

matplotlib.pyplot is a collection of command style functions that make matplotlib work like MATLAB.... matplotlib.pyplot is stateful, in that it keeps track of the current figure and plotting area, and the plotting functions are directed to the current axes

关键是 pyplot 是有状态的。它“在幕后”跟踪状态并在某种程度上向您隐藏对象模型。它还会做一些隐含的事情。所以 - 如果您只是调用,例如 plt.axis(),在幕后 pyplot calls plt.gca()反过来calls gcf()这将return a new figure ,因为您还没有通过 pyplot 设置图形。对于大多数 plt.some_function() 调用都是如此 - 如果 pyplot 没有图形对象在它自己的状态 然而,它会创建一个。

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

妙语

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

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

如何修复

改变

plt.axis('off')
plt.tight_layout()
plt.imshow(image)

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 与直接使用对象

这有点意见,但可能会有所帮助。当我需要快速制作原型(prototype)并希望使用其中一个相当标准的案例时,我倾向于使用 pyplot 界面。通常,这就足够了。

一旦我需要做更复杂的事情,我就开始直接使用对象模型——维护我自己命名的 FigureAxes 对象等。

将两者混合使用是可能的,但通常会造成混淆。您已经通过中间解决方案找到了这一点。所以我建议做一个或另一个。

关于python - 为什么 matplotlib.figure.Figure 的行为与 matplotlib.pyplot.figure 如此不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31611188/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com