首页 > 解决方案 > 如何使用 Tkinter 在 python 中使 Matplotlib 光标在没有鼠标的情况下显示

问题描述

我在 Tkinter 的画布上有一个、两个或三个图。假设我没有鼠标。只有一个键盘。我希望这些绘图上的光标在画布中的所有图表上沿同一水平轴移动,当然当 Tk 窗口显示所有图表上的黄色光标(mplcursors)时,所有图表上的黄色光标(mplcursors)都位于图表的第一个点,没有任何鼠标移动和点击(如果你运行下面的代码有黄色和绿色两个光标,黄色通过点击行出现)。黄色光标必须通过键盘上的右/左箭头键一起移动(相同的 x 轴点)。

from matplotlib.widgets import MultiCursor
import matplotlib.pyplot as plt
import numpy as np
from tkinter import *
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import mplcursors

root = Tk()

fig = Figure(figsize=(8,6))

fig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True)

x = np.linspace(-np.pi, np.pi, 256, endpoint=True)
y = np.sin(x)
z = np.cos(x)

ax1.plot(x, y, label="sin function")
ax1.legend(loc="upper right")
ax2.plot(x, z, label="cos function")
canvas = FigureCanvasTkAgg(fig,root)

c1 = mplcursors.cursor(ax1, multiple=False,hover=False,highlight=False,bindings={"toggle_visible": "h", "toggle_enabled": "e","left": "left","right": "right"})
c2 = mplcursors.cursor(ax2, multiple=False,hover=False,highlight=False,bindings={"toggle_visible": "h", "toggle_enabled": "e","left": "left","right": "right"})

multi = MultiCursor(fig.canvas, (ax1, ax2), color='g', lw=0.5, horizOn=True, vertOn=True)

ax2.legend(loc="upper left")

canvas.draw()
#pack canavs
canvas.get_tk_widget().pack(side = BOTTOM, fill=BOTH, expand=True)
#create Navigation Toolbar

toolbar = NavigationToolbar2Tk(canvas, root) #add to canvas
canvas._tkcanvas.pack(side = TOP, fill=BOTH, expand=True)

root.mainloop()

你有什么建议吗?我还可以让多光标(绿线)在绘图上随 mplcursors 移动并坚持它们吗?

我已经尝试从此链接进行多线程处理,从链接使用鼠标控制并通过此问题获取第一个绘图点的像素,但我无法处理第一个显示事件,并且需要分别在两个绘图上单击鼠标才能显示游标。

我的情节更复杂,它们是信号,我的应用程序中有多个页面。

标签: pythonmatplotlibtkinter

解决方案


以下代码可以满足我的要求,但无法解决将绿色多光标保持在黄色光标上的问题!(还在探索中)

下面的代码使用 MouseEvent 和 _process_event ,默认情况下点击情节,调用它时你应该声明这个过程何时发生?,在哪个情节,在哪个点!

from matplotlib.widgets import MultiCursor
import matplotlib.pyplot as plt
import numpy as np
from tkinter import *
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import mplcursors
import subprocess
from matplotlib.backend_bases import KeyEvent, MouseEvent
import copy

def _process_event(name, ax, coords, *args):
    ax.viewLim  # unstale viewLim.
    if name == "__mouse_click__":
        # So that the dragging callbacks don't go crazy.
        _process_event("button_press_event", ax, coords, *args)
        _process_event("button_release_event", ax, coords, *args)
        return
    display_coords = ax.transData.transform(coords)
    if name in ["button_press_event", "button_release_event",
                "motion_notify_event", "scroll_event"]:
        event = MouseEvent(name, ax.figure.canvas, *display_coords, *args)
    elif name in ["key_press_event", "key_release_event"]:
        event = KeyEvent(name, ax.figure.canvas, *args, *display_coords)
    else:
        raise ValueError(f"Unknown event name {name!r}")
    ax.figure.canvas.callbacks.process(name, event)

root = Tk()

fig = Figure(figsize=(8,6))

fig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True)

x = np.linspace(-np.pi, np.pi, 256, endpoint=True)
y = np.sin(x)
z = np.cos(x)

ax1.plot(x, y, label="sin function")
ax1.legend(loc="upper right")
ax2.plot(x, z, label="cos function")
canvas = FigureCanvasTkAgg(fig,root)

c1 = mplcursors.cursor(ax1, multiple=False,hover=False,highlight=False,bindings={"toggle_visible": "h", "toggle_enabled": "e","left": "left","right": "right"})
c2 = mplcursors.cursor(ax2, multiple=False,hover=False,highlight=False,bindings={"toggle_visible": "h", "toggle_enabled": "e","left": "left","right": "right"})

multi = MultiCursor(fig.canvas, (ax1, ax2), color='g', lw=0.5, horizOn=True, vertOn=True)

ax2.legend(loc="upper left")
_process_event("__mouse_click__", ax1, (x[0], y[0]), 1)
sel, = c1.selections
c1.add_selection(copy.copy(sel))

_process_event("__mouse_click__", ax2, (x[0], z[0]), 1)
sel2, = c2.selections
c2.add_selection(copy.copy(sel2))
canvas.draw()
#pack canavs
canvas.get_tk_widget().pack(side = BOTTOM, fill=BOTH, expand=True)
#create Navigation Toolbar

toolbar = NavigationToolbar2Tk(canvas, root) #add to canvas
canvas._tkcanvas.pack(side = TOP, fill=BOTH, expand=True)
root.mainloop()

推荐阅读