当在 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()
我在 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()