当在 tkinter 中嵌入的两个 matplotlib 图之间切换时,第一张图上会出现一组额外的意外 x 和 y 轴标签和刻度

When switching between two matplotlib graphs embedded in tkinter an extra unexpected set of x an y axis labels and ticks appears on the first graph

我在 tkinter 中嵌入了两个不同的 matplotlib 图,我使用一个按钮在它们之间切换。第一个图形切换周期按预期绘制图形,但是此后每次在两个图形之间切换都会导致第一个图形具有意外的 x 和 y 轴标签集和从 0 到 1 的刻度。所需的图形一个 x 和 y 轴标签和刻度按预期存在,但另外一个额外的 0 到 1 范围 labels/ticks 覆盖在预期的 labels/ticks 上。图的两个 x 轴和 y 轴 labels/ticks 表现正确,没有意外的叠加。以下是我的代码的简化版本,后面是一些显示问题的图表图片。

import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from tkinter import *
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, 
NavigationToolbar2Tk)
from matplotlib.backend_bases import key_press_handler
import numpy as np

# Separated out config of plot to just do it once
def config_plot():
    fig = plt.figure(figsize=(18, 5))
    return (fig)



class graphSwitcher:
    def __init__(self, master):
        self.master = master
        self.frame = Frame(self.master)
        self.fig = config_plot()
        self.graphIndex = 0
        self.canvas = FigureCanvasTkAgg(self.fig, self.master)
        self.config_window()
        self.graph_one(self.fig)
        self.frame.pack(expand=YES, fill=BOTH)


    def config_window(self):
        self.canvas.mpl_connect("key_press_event", self.on_key_press)
        toolbar = NavigationToolbar2Tk(self.canvas, self.master)
        toolbar.update()
        self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, 
expand=1)
        self.button = Button(self.master, text="Quit", 
command=self._quit)
        self.button.pack(side=BOTTOM)
        self.button_switch = Button(self.master, text="Switch Graphs", 
command=self.switch_graphs)
        self.button_switch.pack(side=BOTTOM)
        plt.subplots_adjust(bottom=0.2)


    # the def creates the first matplotlib graph
    def graph_one(self, fig):
        t = np.arange(0.0, 2.0, 0.01)
        s = 1 + np.sin(2 * np.pi * t)

        self.ax = fig.subplots()
        try:
            self.ax1.clear()  # clear current axes
            self.ax2.clear()
        except AttributeError:
            pass

        self.ax.plot(t, s)

        self.ax.set(xlabel='time (s)', ylabel='voltage (mV)',
                   title='Graph One')

        self.canvas.draw()

    # This def creates the second matplotlib graph that uses subplot
    # to place two graphs one on top of the other
    def graph_two(self, fig):
        x1 = np.linspace(0.0, 5.0)
        y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
        self.ax1 = plt.subplot2grid((5, 4), (0, 0), rowspan=4, 
colspan=4)
        self.ax1.plot(x1, y1, 'o-')
        self.ax1.set(title='Graph Two')

        means_men = (20, 35, 30, 35, 27)
        std_men = (2, 3, 4, 1, 2)
        self.ax2 = plt.subplot2grid((5, 4), (4, 0), sharex=self.ax1, 
rowspan=1, colspan=4)
        self.ax2.bar(std_men, means_men, color='green', width=0.5,
                align='center')

        self.canvas.draw()

    def on_key_press(event):
        key_press_handler(event, canvas, toolbar)

    def _quit(self):
        self.master.quit()  # stops mainloop

    def switch_graphs(self):
        self.graphIndex = (self.graphIndex + 1 ) % 2
        if self.graphIndex == 0:
            self.graph_one(self.fig)
        else:
            self.graph_two(self.fig)



def main():
    root = Tk()
    graphSwitcher(root)
    root.mainloop()

if __name__ == '__main__':
    main()

以下是按顺序看到的图表的图片,显示了前两次看到单个图表(第 1 个周期)的图表具有正确的轴标签和刻度。但是第二次显示第一个图表时,有一组额外的意想不到的 x 和 y 轴标签和刻度。最后两张图在每个周期重复一次(两次按钮按下)

如果有人对如何消除图一中意外的 x 轴和 y 轴 labels/ticks 有任何想法,我将不胜感激。

您正在 清除 在调用 graph_two 时创建的轴,但您没有 删除 它们。因此,当您第二次绘制第一个图形时,graph_two 轴仍然位于 graph_one 的轴下方。您看不到 2 个子图本身,因为它们位于下方,但轴刻度标签确实显示在边缘,这就是您所看到的。

如果您删除graph_one中的绘图和图形创建,这将更容易看到,您将能够看到当您按下按钮时,2 个子图被清除但没有被删除。

解决方法很简单,改用axes.remove。所以 graph_one 看起来像:

def graph_one(self, fig):
    t = np.arange(0.0, 2.0, 0.01)
    s = 1 + np.sin(2 * np.pi * t)

    self.ax = fig.subplots()
    try:
        self.ax1.remove()  # remove current axes
        self.ax2.remove()
    except AttributeError:
        pass

    self.ax.plot(t, s)

    self.ax.set(xlabel='time (s)', ylabel='voltage (mV)',
               title='Graph One')

    self.canvas.draw()