[英]How to resize a Python matplotlib.pyplot.figure already created
[英]Why does matplotlib.figure.Figure behave so different than matplotlib.pyplot.figure
一位同事程序员提醒我一个matplotlib.pyplot和Tkinter不能很好地协同工作的问题,正如这个问题所证明的那样Tkinter / Matplotlib后端冲突导致无限主循环
我们更改了代码以防止链接问题中提到的潜在问题,如下所示:
旧
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
变体的任何好文档。
因此,问题是,为什么我们现在需要使用子图(使用matplotlib.figure.Figure)而不是之前(使用matplotlib.pyplot)?
subplot
创建一个Axes
对象。 你之前确实有过一个,但是pyplot
API“隐藏”了你的封面所以你没有意识到它。 您现在正在尝试直接使用这些对象,因此必须自己处理它。
您看到此行为的原因是因为matplotlib.pyplot
工作原理。 引用教程一点:
matplotlib.pyplot
是命令样式函数的集合,它使matplotlib像MATLAB一样工作....matplotlib.pyplot
是有状态的,因为它跟踪当前的图形和绘图区域,绘图函数指向当前轴
关键是pyplot
是有状态的。 它正在跟踪状态“隐藏”并在某种程度上隐藏对象模型。 它也做了一些隐含的事情。 所以 - 如果你只是调用,例如, plt.axis()
,在封面下pyplot
调用plt.gca()
,然后调用gcf()
,这将返回一个新的数字 ,因为你还没有设置一个数字pyplot
呢。 大多数对plt.some_function()
调用都是如此 - 如果pyplot
在它自己的状态中没有一个figure对象,它将创建一个。
所以,在你的中间例子中,你已经创建了自己的Figure
对象 - 这就是一个名字self.fig
(我不确定你的类结构是什么,所以我不知道self
是什么,但我猜它是你的tk.Frame
对象或类似的东西)。
pyplot
对self.fig
。 因此,在您的中间代码中,您在pyplot
状态下调用Figure
对象上的imshow()
,但在画布上显示不同的图形( self.fig
)。
问题不是您需要使用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与直接使用对象 这有点意见,但可能有所帮助。 当我需要快速获取原型并希望使用其中一个相当标准的情况时,我倾向于使用pyplot
接口。 通常,这就足够了。
一旦我需要做更复杂的事情,我就开始直接使用对象模型 - 维护我自己的名为Figure
和Axes
对象等。
混合这两者是可能的,但往往令人困惑。 您已经在中间解决方案中找到了这个。 所以我建议做一个或另一个。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.