maplotlib.widgets 与 FuncAnimation
maplotlib.widgets with FuncAnimation
我正在尝试使用 animation.FuncAnimation 实时绘制串行数据,并且我希望能够为控制器设置一个目标值。所以我想在图形上有一个可编辑的文本框,它由标记为 target
的行实时反映,但我不知道如何将文本框与 FuncAnimation 合并。当我将文本框代码放在循环函数之外时,它什么都不做(但绘图有效)但是当它在循环内时,文本框出现在图形的中间并且绘图不再有效。非常感谢任何帮助。
import matplotlib.pyplot as plt
from matplotlib.widgets import TextBox
import matplotlib.animation as animation
import time
import random
target = float(0.0)
def changeTarget(text):
try:
target = float(text)
except ValueError:
print(text + " is not a number")
def loop(i):
t.append(time.time() - tic)
data.append(random.random())
target_data.append(target)
ax.clear()
ax.plot(t, data, label='data')
ax.plot(t, target_data, label='target')
ax.set_xlabel('Time (s)')
ax.set_ylabel('Data')
ax.set_xlim([t[-1]-15, t[-1]+5])
ax.set_ylim([min(min(data), min(target_data))-5, max(max(data), max(target_data))+5])
ax.legend()
# This part causes problems
text_box = TextBox(ax, 'Target:', initial="0")
text_box.on_submit(changeTarget)
plt.draw()
t = []
data = []
target_data = []
fig, ax = plt.subplots()
# text_box = TextBox(ax, 'Target:', initial="0")
# text_box.on_submit(changeTarget)
# plt.draw()
tic = time.time()
ani = animation.FuncAnimation(fig, loop, interval = 100)
plt.show()
编辑:删除随机数据上的 10 倍乘数表明绘图确实有效,但看起来 window 没有按预期更新,并且小部件仍然位于轴的顶部并且不可编辑。
我想出了一个使用 tkinter 来做到这一点的方法:
import tkinter as tk
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
import matplotlib.animation as animation
import time
import random
window = tk.Tk()
# Target entry box
frm_target = tk.Frame(master=window)
ent_humidity = tk.Entry(master=frm_target, width=3)
lbl_hum = tk.Label(master=frm_target, text="Target: ")
lbl_hum.grid(row=0, column=0, sticky="e")
ent_humidity.grid(row=0, column=1, sticky="w")
frm_target.pack()
# Set Target when user hits Enter
target = float(0.0)
def onEnterPressed(event):
global target
text = ent_humidity.get()
try:
target = float(text)
except ValueError:
print(text + " is not a number")
window.bind('<Return>', onEnterPressed)
# Figure for plotting
fig = Figure(figsize=(5, 4), dpi=100)
ax = fig.add_subplot(111)
# "Data" collection logic
t = []
data = []
target_data = []
def loop(i):
t.append(time.time() - tic)
data.append(random.random() * 10)
target_data.append(target)
ax.clear()
ax.plot(t, data, label='data')
ax.plot(t, target_data, label='target')
ax.set_xlabel('Time (s)')
ax.set_ylabel('Data')
ax.set_xlim([t[-1]-15, t[-1]+5])
ax.set_ylim([min(min(data), min(target_data))-5, max(max(data), max(target_data))+5])
ax.legend()
# GUI stuff for figure & toolbar
canvas = FigureCanvasTkAgg(fig, master=window)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
toolbar = NavigationToolbar2Tk(canvas, window)
toolbar.update()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
# Quit button
def _quit():
window.quit()
window.destroy()
button = tk.Button(master=window, text="Quit", command=_quit)
button.pack(side=tk.BOTTOM)
# Run app
tic = time.time()
ani = animation.FuncAnimation(fig, loop, interval=100) # interval in ms
tk.mainloop()
我正在尝试使用 animation.FuncAnimation 实时绘制串行数据,并且我希望能够为控制器设置一个目标值。所以我想在图形上有一个可编辑的文本框,它由标记为 target
的行实时反映,但我不知道如何将文本框与 FuncAnimation 合并。当我将文本框代码放在循环函数之外时,它什么都不做(但绘图有效)但是当它在循环内时,文本框出现在图形的中间并且绘图不再有效。非常感谢任何帮助。
import matplotlib.pyplot as plt
from matplotlib.widgets import TextBox
import matplotlib.animation as animation
import time
import random
target = float(0.0)
def changeTarget(text):
try:
target = float(text)
except ValueError:
print(text + " is not a number")
def loop(i):
t.append(time.time() - tic)
data.append(random.random())
target_data.append(target)
ax.clear()
ax.plot(t, data, label='data')
ax.plot(t, target_data, label='target')
ax.set_xlabel('Time (s)')
ax.set_ylabel('Data')
ax.set_xlim([t[-1]-15, t[-1]+5])
ax.set_ylim([min(min(data), min(target_data))-5, max(max(data), max(target_data))+5])
ax.legend()
# This part causes problems
text_box = TextBox(ax, 'Target:', initial="0")
text_box.on_submit(changeTarget)
plt.draw()
t = []
data = []
target_data = []
fig, ax = plt.subplots()
# text_box = TextBox(ax, 'Target:', initial="0")
# text_box.on_submit(changeTarget)
# plt.draw()
tic = time.time()
ani = animation.FuncAnimation(fig, loop, interval = 100)
plt.show()
编辑:删除随机数据上的 10 倍乘数表明绘图确实有效,但看起来 window 没有按预期更新,并且小部件仍然位于轴的顶部并且不可编辑。
我想出了一个使用 tkinter 来做到这一点的方法:
import tkinter as tk
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
import matplotlib.animation as animation
import time
import random
window = tk.Tk()
# Target entry box
frm_target = tk.Frame(master=window)
ent_humidity = tk.Entry(master=frm_target, width=3)
lbl_hum = tk.Label(master=frm_target, text="Target: ")
lbl_hum.grid(row=0, column=0, sticky="e")
ent_humidity.grid(row=0, column=1, sticky="w")
frm_target.pack()
# Set Target when user hits Enter
target = float(0.0)
def onEnterPressed(event):
global target
text = ent_humidity.get()
try:
target = float(text)
except ValueError:
print(text + " is not a number")
window.bind('<Return>', onEnterPressed)
# Figure for plotting
fig = Figure(figsize=(5, 4), dpi=100)
ax = fig.add_subplot(111)
# "Data" collection logic
t = []
data = []
target_data = []
def loop(i):
t.append(time.time() - tic)
data.append(random.random() * 10)
target_data.append(target)
ax.clear()
ax.plot(t, data, label='data')
ax.plot(t, target_data, label='target')
ax.set_xlabel('Time (s)')
ax.set_ylabel('Data')
ax.set_xlim([t[-1]-15, t[-1]+5])
ax.set_ylim([min(min(data), min(target_data))-5, max(max(data), max(target_data))+5])
ax.legend()
# GUI stuff for figure & toolbar
canvas = FigureCanvasTkAgg(fig, master=window)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
toolbar = NavigationToolbar2Tk(canvas, window)
toolbar.update()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
# Quit button
def _quit():
window.quit()
window.destroy()
button = tk.Button(master=window, text="Quit", command=_quit)
button.pack(side=tk.BOTTOM)
# Run app
tic = time.time()
ani = animation.FuncAnimation(fig, loop, interval=100) # interval in ms
tk.mainloop()