在多个子图上跟随鼠标的垂直光标
Vertical cursor following mouse on multiple subplots
我正在编写一个供个人使用的小脚本,旨在形成一些数据记录以便能够对其进行分析。
我的想法是选择我想查看的数据,然后检查它们,它们将显示在多个子批次上。
我将 Python 与 tkinter 和 matplotlib 一起使用。
我目前遇到的问题是我想在鼠标移动后有一个垂直光标,并且我希望这个光标在所有显示的子图中都相同。
我正在尝试使用 matplotlib 中的“MultiCursor”,但它不起作用而且我没有错误。
我认为问题在于我将子图列表作为参数提供给 MultiCursor,但在我的代码中我看不到如何通过其他方式来实现它。
如有任何想法或意见,我们将不胜感激。
最小可复制代码:
import tkinter as tk
from matplotlib.widgets import MultiCursor
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
w_main = tk.Tk()
w_main.geometry("1080x720")
f_leftFrame = tk.Frame(w_main)
f_leftFrame.pack(side=tk.LEFT, anchor='nw', fill=tk.BOTH)
f_graphFrame = tk.Frame(w_main)
f_graphFrame.pack(fill=tk.BOTH, expand=1)
fig = Figure(figsize=(5, 5), dpi=100)
graph = FigureCanvasTkAgg(fig, master=f_graphFrame)
graph.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
time = [0, 0.150, 0.3, 0.450, 0.6, 0.750, 0.9]
record1 = [0, 5, 3, 6, 2, 8, 9]
record2 = [1, 6, 8, 5, 7, 2, 5]
record3 = [9, 7, 5, 3, 0, 0, 2]
labels = ["record1", "record2", "record3"]
dic_state_cb = {}
test_list = []
def curveBuilder():
dic_state_cb = {}
sel_curves = []
global test_list
for i in labels:
dic_state_cb["state_{}".format(i)] = globals()["state_{}".format(i)].get()
if dic_state_cb["state_{}".format(i)] == 1:
sel_curves.append(i)
for i in range(len(labels)):
try:
globals()["ax{}".format(i)].remove()
test_list = []
except:
pass
for i in range(len(sel_curves)):
globals()["ax{}".format(i)] = fig.add_subplot(int("{}1{}".format(len(sel_curves), i+1)))
test_list.append(globals()["ax{}".format(i)])
x = time
if len(sel_curves) > 0:
for i in range(len(sel_curves)):
curve = globals()[sel_curves[i]]
test_list[i].plot(x, curve)
test_list[i].set_ylabel(sel_curves[i])
if i < len(sel_curves) - 1:
x_axis = test_list[i].axes.get_xaxis()
x_axis.set_visible(False)
multi = MultiCursor(graph, test_list, color="'r'", lw=2.0, vertOn=True)
graph.draw()
for i in enumerate(labels):
globals()["state_{}".format(i[1])] = tk.IntVar()
cb = tk.Checkbutton(f_leftFrame, text=i[1], variable=globals()["state_{}".format(i[1])], command=curveBuilder,
anchor=tk.W)
cb.pack(fill=tk.BOTH)
tk.mainloop()
终于我自己找到了答案。
问题来自包含 MultiCursor 调用结果的变量,该结果对于我的代码中的函数是本地的。如果我将它声明为全局变量,那么它就可以正常工作。
我不太明白为什么,但它解决了问题。我希望知道为什么会发生的人在这里给出答案。
这里是工作代码:
import tkinter as tk
from matplotlib.widgets import MultiCursor
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
w_main = tk.Tk()
w_main.geometry("1080x720")
f_leftFrame = tk.Frame(w_main)
f_leftFrame.pack(side=tk.LEFT, anchor='nw', fill=tk.BOTH)
f_graphFrame = tk.Frame(w_main)
f_graphFrame.pack(fill=tk.BOTH, expand=1)
fig = Figure(figsize=(5, 5), dpi=100)
graph = FigureCanvasTkAgg(fig, master=f_graphFrame)
graph.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
time = [0, 0.150, 0.3, 0.450, 0.6, 0.750, 0.9]
record1 = [0, 5, 3, 6, 2, 8, 9]
record2 = [1, 6, 8, 5, 7, 2, 5]
record3 = [9, 7, 5, 3, 0, 0, 2]
labels = ["record1", "record2", "record3"]
dic_state_cb = {}
test_list = []
def curveBuilder():
dic_state_cb = {}
sel_curves = []
global test_list
for i in labels:
dic_state_cb["state_{}".format(i)] = globals()["state_{}".format(i)].get()
if dic_state_cb["state_{}".format(i)] == 1:
sel_curves.append(i)
for i in range(len(labels)):
try:
globals()["ax{}".format(i)].remove()
test_list = []
except:
pass
for i in range(len(sel_curves)):
globals()["ax{}".format(i)] = fig.add_subplot(int("{}1{}".format(len(sel_curves), i+1)))
test_list.append(globals()["ax{}".format(i)])
x = time
if len(sel_curves) > 0:
for i in range(len(sel_curves)):
curve = globals()[sel_curves[i]]
test_list[i].plot(x, curve)
test_list[i].set_ylabel(sel_curves[i])
if i < len(sel_curves) - 1:
x_axis = test_list[i].axes.get_xaxis()
x_axis.set_visible(False)
global multi
multi = MultiCursor(graph, test_list, color='r', lw=2.0, vertOn=True)
graph.draw()
for i in enumerate(labels):
globals()["state_{}".format(i[1])] = tk.IntVar()
cb = tk.Checkbutton(f_leftFrame, text=i[1], variable=globals()["state_{}".format(i[1])], command=curveBuilder,
anchor=tk.W)
cb.pack(fill=tk.BOTH)
tk.mainloop()
我正在编写一个供个人使用的小脚本,旨在形成一些数据记录以便能够对其进行分析。 我的想法是选择我想查看的数据,然后检查它们,它们将显示在多个子批次上。 我将 Python 与 tkinter 和 matplotlib 一起使用。
我目前遇到的问题是我想在鼠标移动后有一个垂直光标,并且我希望这个光标在所有显示的子图中都相同。 我正在尝试使用 matplotlib 中的“MultiCursor”,但它不起作用而且我没有错误。 我认为问题在于我将子图列表作为参数提供给 MultiCursor,但在我的代码中我看不到如何通过其他方式来实现它。
如有任何想法或意见,我们将不胜感激。
最小可复制代码:
import tkinter as tk
from matplotlib.widgets import MultiCursor
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
w_main = tk.Tk()
w_main.geometry("1080x720")
f_leftFrame = tk.Frame(w_main)
f_leftFrame.pack(side=tk.LEFT, anchor='nw', fill=tk.BOTH)
f_graphFrame = tk.Frame(w_main)
f_graphFrame.pack(fill=tk.BOTH, expand=1)
fig = Figure(figsize=(5, 5), dpi=100)
graph = FigureCanvasTkAgg(fig, master=f_graphFrame)
graph.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
time = [0, 0.150, 0.3, 0.450, 0.6, 0.750, 0.9]
record1 = [0, 5, 3, 6, 2, 8, 9]
record2 = [1, 6, 8, 5, 7, 2, 5]
record3 = [9, 7, 5, 3, 0, 0, 2]
labels = ["record1", "record2", "record3"]
dic_state_cb = {}
test_list = []
def curveBuilder():
dic_state_cb = {}
sel_curves = []
global test_list
for i in labels:
dic_state_cb["state_{}".format(i)] = globals()["state_{}".format(i)].get()
if dic_state_cb["state_{}".format(i)] == 1:
sel_curves.append(i)
for i in range(len(labels)):
try:
globals()["ax{}".format(i)].remove()
test_list = []
except:
pass
for i in range(len(sel_curves)):
globals()["ax{}".format(i)] = fig.add_subplot(int("{}1{}".format(len(sel_curves), i+1)))
test_list.append(globals()["ax{}".format(i)])
x = time
if len(sel_curves) > 0:
for i in range(len(sel_curves)):
curve = globals()[sel_curves[i]]
test_list[i].plot(x, curve)
test_list[i].set_ylabel(sel_curves[i])
if i < len(sel_curves) - 1:
x_axis = test_list[i].axes.get_xaxis()
x_axis.set_visible(False)
multi = MultiCursor(graph, test_list, color="'r'", lw=2.0, vertOn=True)
graph.draw()
for i in enumerate(labels):
globals()["state_{}".format(i[1])] = tk.IntVar()
cb = tk.Checkbutton(f_leftFrame, text=i[1], variable=globals()["state_{}".format(i[1])], command=curveBuilder,
anchor=tk.W)
cb.pack(fill=tk.BOTH)
tk.mainloop()
终于我自己找到了答案。 问题来自包含 MultiCursor 调用结果的变量,该结果对于我的代码中的函数是本地的。如果我将它声明为全局变量,那么它就可以正常工作。
我不太明白为什么,但它解决了问题。我希望知道为什么会发生的人在这里给出答案。
这里是工作代码:
import tkinter as tk
from matplotlib.widgets import MultiCursor
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
w_main = tk.Tk()
w_main.geometry("1080x720")
f_leftFrame = tk.Frame(w_main)
f_leftFrame.pack(side=tk.LEFT, anchor='nw', fill=tk.BOTH)
f_graphFrame = tk.Frame(w_main)
f_graphFrame.pack(fill=tk.BOTH, expand=1)
fig = Figure(figsize=(5, 5), dpi=100)
graph = FigureCanvasTkAgg(fig, master=f_graphFrame)
graph.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
time = [0, 0.150, 0.3, 0.450, 0.6, 0.750, 0.9]
record1 = [0, 5, 3, 6, 2, 8, 9]
record2 = [1, 6, 8, 5, 7, 2, 5]
record3 = [9, 7, 5, 3, 0, 0, 2]
labels = ["record1", "record2", "record3"]
dic_state_cb = {}
test_list = []
def curveBuilder():
dic_state_cb = {}
sel_curves = []
global test_list
for i in labels:
dic_state_cb["state_{}".format(i)] = globals()["state_{}".format(i)].get()
if dic_state_cb["state_{}".format(i)] == 1:
sel_curves.append(i)
for i in range(len(labels)):
try:
globals()["ax{}".format(i)].remove()
test_list = []
except:
pass
for i in range(len(sel_curves)):
globals()["ax{}".format(i)] = fig.add_subplot(int("{}1{}".format(len(sel_curves), i+1)))
test_list.append(globals()["ax{}".format(i)])
x = time
if len(sel_curves) > 0:
for i in range(len(sel_curves)):
curve = globals()[sel_curves[i]]
test_list[i].plot(x, curve)
test_list[i].set_ylabel(sel_curves[i])
if i < len(sel_curves) - 1:
x_axis = test_list[i].axes.get_xaxis()
x_axis.set_visible(False)
global multi
multi = MultiCursor(graph, test_list, color='r', lw=2.0, vertOn=True)
graph.draw()
for i in enumerate(labels):
globals()["state_{}".format(i[1])] = tk.IntVar()
cb = tk.Checkbutton(f_leftFrame, text=i[1], variable=globals()["state_{}".format(i[1])], command=curveBuilder,
anchor=tk.W)
cb.pack(fill=tk.BOTH)
tk.mainloop()