[英]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.