如何解决 tkinter canvas 中错位的子图?
How to resolve misplaced subplots in tkinter canvas?
我遇到了这个问题,我在父框架的 canvas 上创建了 4 个子图,并且第一次创建图形没问题 ()
第二次,我使用一个函数清除了 canvas,然后再次绘图,但我看到了一张错位的图表和多个 matplotlib 工具栏副本 ()
可重现的例子:
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
import tkinter as tk
def fnc1to2():
print("1 to 2")
frame1.pack_forget()
frame2.pack(fill="both", expand=True)
def fnc2to3():
print("2 to 3")
frame2.pack_forget()
frame3.pack(fill="both", expand=True)
def fnc2to1():
print("2 to 1")
frame2.pack_forget()
frame1.pack(fill="both", expand=True)
def fnc3to2():
print("3 to 2")
frame3.pack_forget()
frame2.pack(fill="both", expand=True)
def fileget():
global f
f = Figure(figsize=(3,3), dpi=100,constrained_layout=True)
f.set_constrained_layout_pads(w_pad=9 / 72, h_pad=4 / 72, hspace=0.2,
wspace=0.15)
#a = f.add_subplot(221,xlim=(t[0],t[-1]),ylim=(-3000,3000))
#fig1, ax = matplotlib.pyplot.subplots()
a = f.add_subplot(221)
a.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
#a.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a1 = f.add_subplot(222)
a1.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a1.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
a2 = f.add_subplot(223)
a2.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a2.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
a3 = f.add_subplot(224)
a3.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a3.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
global canvas1
canvas1 = FigureCanvasTkAgg(f, frame3)
canvas1.draw()
canvas1.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
toolbar = NavigationToolbar2Tk(canvas1, frame3)
toolbar.update()
canvas1._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
def clearplot():
f.clear()
#f.clf()
for item in canvas1.get_tk_widget().find_all():
canvas1.get_tk_widget().delete(item)
canvas1.draw()
root = tk.Tk()
root.geometry("1280x1080")
frame1 = tk.Frame(root, bg = "azure3")
frame2 = tk.Frame(root, bg = "seashell2")
frame3 = tk.Frame(root, bg = "honeydew2")
#lab1f1 = tk.Label(frame1, text = "Label 1 in Frame 1")
lab1f2 = tk.Label(frame2, text = "Label 1 in Frame 2")
lab1f3 = tk.Label(frame3, text = "Manual log analysis", font=12)
btn1to2 = tk.Button(frame1, text = "Start", command = fnc1to2)
btn2to1 = tk.Button(frame2, text = "Back to home", command = fnc2to1)
btn2to3 = tk.Button(frame2, text = "Manual log", command = fnc2to3)
btn3to2 = tk.Button(frame3, text = "Select log type", command = fnc3to2)
btn3to3 = tk.Button(frame3, text = "Connect", command = fileget)
btn3reset = tk.Button(frame3, text = "Clear", command = clearplot)
#frame 1
btn1to2.pack()
#frame 2
f2label = tk.Label(frame2, text="Select log type to visualize!!!", font=12)
f2label.pack(pady=10,padx=10)
lab1f2.pack()
btn2to3.pack()
btn2to1.pack()
#frame 3
lab1f3.pack()
btn3to3.pack()
btn3to2.pack()
btn3reset.pack()
frame1.pack(fill="both", expand=True)
root.mainloop()
因为每次执行fileget()
都会新建一组图形和工具栏。您需要通过在 fileget()
.
开头调用 clearplot()
来删除之前的一组图形和工具栏
下面是修改后的fileget()
和clearplot()
:
def fileget():
global f, canvas1, toolbar
clearplot() # destroy previous figure and toolbar
f = Figure(figsize=(3,3), dpi=100, constrained_layout=True)
f.set_constrained_layout_pads(w_pad=9/72, h_pad=4/72, hspace=0.2, wspace=0.15)
a = f.add_subplot(221)
a.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
a1 = f.add_subplot(222)
a1.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a1.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
a2 = f.add_subplot(223)
a2.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a2.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
a3 = f.add_subplot(224)
a3.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a3.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
canvas1 = FigureCanvasTkAgg(f, frame3)
canvas1.draw()
canvas1.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
toolbar = NavigationToolbar2Tk(canvas1, frame3)
toolbar.update()
def clearplot():
global canvas1, toolbar
try:
canvas1.get_tk_widget().destroy()
toolbar.destroy()
except:
# canvas1 and toolbar do not exist
pass
我遇到了这个问题,我在父框架的 canvas 上创建了 4 个子图,并且第一次创建图形没问题 (
第二次,我使用一个函数清除了 canvas,然后再次绘图,但我看到了一张错位的图表和多个 matplotlib 工具栏副本 (
可重现的例子:
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
import tkinter as tk
def fnc1to2():
print("1 to 2")
frame1.pack_forget()
frame2.pack(fill="both", expand=True)
def fnc2to3():
print("2 to 3")
frame2.pack_forget()
frame3.pack(fill="both", expand=True)
def fnc2to1():
print("2 to 1")
frame2.pack_forget()
frame1.pack(fill="both", expand=True)
def fnc3to2():
print("3 to 2")
frame3.pack_forget()
frame2.pack(fill="both", expand=True)
def fileget():
global f
f = Figure(figsize=(3,3), dpi=100,constrained_layout=True)
f.set_constrained_layout_pads(w_pad=9 / 72, h_pad=4 / 72, hspace=0.2,
wspace=0.15)
#a = f.add_subplot(221,xlim=(t[0],t[-1]),ylim=(-3000,3000))
#fig1, ax = matplotlib.pyplot.subplots()
a = f.add_subplot(221)
a.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
#a.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a1 = f.add_subplot(222)
a1.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a1.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
a2 = f.add_subplot(223)
a2.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a2.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
a3 = f.add_subplot(224)
a3.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a3.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
global canvas1
canvas1 = FigureCanvasTkAgg(f, frame3)
canvas1.draw()
canvas1.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
toolbar = NavigationToolbar2Tk(canvas1, frame3)
toolbar.update()
canvas1._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
def clearplot():
f.clear()
#f.clf()
for item in canvas1.get_tk_widget().find_all():
canvas1.get_tk_widget().delete(item)
canvas1.draw()
root = tk.Tk()
root.geometry("1280x1080")
frame1 = tk.Frame(root, bg = "azure3")
frame2 = tk.Frame(root, bg = "seashell2")
frame3 = tk.Frame(root, bg = "honeydew2")
#lab1f1 = tk.Label(frame1, text = "Label 1 in Frame 1")
lab1f2 = tk.Label(frame2, text = "Label 1 in Frame 2")
lab1f3 = tk.Label(frame3, text = "Manual log analysis", font=12)
btn1to2 = tk.Button(frame1, text = "Start", command = fnc1to2)
btn2to1 = tk.Button(frame2, text = "Back to home", command = fnc2to1)
btn2to3 = tk.Button(frame2, text = "Manual log", command = fnc2to3)
btn3to2 = tk.Button(frame3, text = "Select log type", command = fnc3to2)
btn3to3 = tk.Button(frame3, text = "Connect", command = fileget)
btn3reset = tk.Button(frame3, text = "Clear", command = clearplot)
#frame 1
btn1to2.pack()
#frame 2
f2label = tk.Label(frame2, text="Select log type to visualize!!!", font=12)
f2label.pack(pady=10,padx=10)
lab1f2.pack()
btn2to3.pack()
btn2to1.pack()
#frame 3
lab1f3.pack()
btn3to3.pack()
btn3to2.pack()
btn3reset.pack()
frame1.pack(fill="both", expand=True)
root.mainloop()
因为每次执行fileget()
都会新建一组图形和工具栏。您需要通过在 fileget()
.
clearplot()
来删除之前的一组图形和工具栏
下面是修改后的fileget()
和clearplot()
:
def fileget():
global f, canvas1, toolbar
clearplot() # destroy previous figure and toolbar
f = Figure(figsize=(3,3), dpi=100, constrained_layout=True)
f.set_constrained_layout_pads(w_pad=9/72, h_pad=4/72, hspace=0.2, wspace=0.15)
a = f.add_subplot(221)
a.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
a1 = f.add_subplot(222)
a1.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a1.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
a2 = f.add_subplot(223)
a2.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a2.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
a3 = f.add_subplot(224)
a3.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
a3.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
canvas1 = FigureCanvasTkAgg(f, frame3)
canvas1.draw()
canvas1.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
toolbar = NavigationToolbar2Tk(canvas1, frame3)
toolbar.update()
def clearplot():
global canvas1, toolbar
try:
canvas1.get_tk_widget().destroy()
toolbar.destroy()
except:
# canvas1 and toolbar do not exist
pass