【问题标题】:tkinter figure (with colorbar) shrinks every time it's displayedtkinter 图形(带颜色条)每次显示时都会缩小
【发布时间】:2020-06-09 19:12:23
【问题描述】:

这是一个 tkinter 程序,从我正在处理的 GUI 中总结出来:

import tkinter as tk
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)

class App(tk.Tk):
    def __init__(self):
        super(App, self).__init__()
        self.main_frame = tk.Frame(self,)
        self.main_frame.pack(fill=tk.BOTH, expand=1)
        
        self.plot1_button = tk.Button(self.main_frame, text='Plot 1',
                                      command=self.draw_plot1)
        self.plot1_button.pack(fill=tk.X,expand=1)
        
        self.plot2_button = tk.Button(self.main_frame, text='Plot 2',
                                      command=self.draw_plot2)
        self.plot2_button.pack(fill=tk.X,expand=1)

        self.FIG, self.AX = plt.subplots()
        self.canvas = FigureCanvasTkAgg(self.FIG, master=self.main_frame)   
        self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.toolbar = NavigationToolbar2Tk(self.canvas, self.main_frame)
        self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        
    def draw_plot1(self):
        self.clear_axes()
        fig = self.AX.plot(np.random.rand(10),np.random.rand(10), color='red')
        self.canvas.draw_idle()
        self.toolbar.update()      
        
    def draw_plot2(self):
        self.clear_axes()
        im = self.AX.matshow(np.random.rand(100,100))
        self.canvas.draw_idle()
        self.toolbar.update()
        cb = plt.colorbar(im, ax=self.AX)
    
    def clear_axes(self):
        for ax in self.FIG.axes:
            ax.clear()
            if ax != self.AX:
                ax.remove()
root = App()
root.resizable(False, False)
root.mainloop()

Plot 1 按钮绘制随机线图,而 Plot 2 按钮绘制带有颜色条的随机热图。可以重复单击 Plot 1 按钮,按预期创建新的随机线图。点击 10 次后,显示效果很好:

:

但是 Plot 2 按钮每次点击都会使图形缩小。点击 10 次后,图表无法解释:

此外,再次单击 Plot 1 时,图形大小仍然存在:

这些是从应用程序工具栏中保存的.png 文件,但在 GUI 窗口中可以看到相同的文件。我尝试在不同位置向 GUI/画布(例如 self.update()self.canvas.draw_idle())添加更新,但没有发现任何影响问题的东西。我添加了 clear_axes() 函数,因为在真实的 GUI 中我有一些带有多个 axes 的图形,这会删除它们,但显然它在这里没有帮助。

我发现如果去掉彩条,问题就消失了(即注释掉cb = plt.colorbar(im, ax=self.AX)),但我想把它作为图中的一部分。任何人都可以阐明正在发生的事情,或者任何人都可以提出解决方案吗?我在matplotlib 3.2.1

【问题讨论】:

    标签: python matplotlib tkinter colorbar


    【解决方案1】:

    问题是您在清除轴时没有清除colorbar

    class App(tk.Tk):
        def __init__(self):
            super(App, self).__init__()
            self.main_frame = tk.Frame(self,)
            ...
            self.cb = None
    
        ...
    
        def draw_plot2(self):
            self.clear_axes()
            im = self.AX.matshow(np.random.rand(100,100))
            self.canvas.draw_idle()
            self.toolbar.update()
            self.cb = plt.colorbar(im, ax=self.AX)
    
        def clear_axes(self):
            if self.cb:
                self.cb.remove()
                self.cb = None
            for ax in self.FIG.axes:
                ax.clear()
                if ax != self.AX:
                    ax.remove()
    

    还请注意,在使用tkinter 时,您应该使用matplotlib.figure.Figure 而不是pyplot。官方示例见this

    【讨论】:

    • 非常感谢,帮了大忙!
    • 你说你不应该不要用pyplottkinter,我以前没听说过。有什么缺点?
    • 如果您有 GUI 和 pyplot 管理图形,它们可能会干扰并导致所有问题。对于初学者,当您退出 GUI 时,由于 pyplot 在不同的线程上运行,您的脚本可能无法正确退出。创建Figure 类是为了使用tkinter 接口安全地嵌入matplotlib 图形。
    • 不错的答案。我遇到了类似的问题;但是,我仍然找不到更好的方法。 stackoverflow.com/questions/70530615/…你介意给我一些建议吗?谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-16
    • 2017-05-13
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多