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

时间:2019-01-17 16:00:37

标签: python matplotlib tkinter tkinter-canvas

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

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轴标签和刻度。 las的两个图在每个周期重复一次(两次按按钮) Cycle 1 Graph 1

Cycle 1 Graph 2

Cycle 2 Graph 1

Cycle 2 Graph 2

如果有人对如何摆脱在图一中看到的意外的x和y轴标签/标记有任何想法,我将不胜感激。

1 个答案:

答案 0 :(得分:1)

您正在清除调用graph_two时创建的轴,但不是移除。因此,当您第二次绘制第一张图时,graph_two轴仍位于graph_one的轴下方。您无法看到它们下面的两个子图,但是刻度线的轴确实显示在边缘,这就是您所看到的。

如果您在graph_one中删除绘图和图形创建,则更容易看到这一点,您将可以看到在按下该按钮时,两个子图被清除,但未被删除。

因此,解决方案很简单,请改用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()