我正在尝试创建拖放功能,您可以从列表框中选择要绘制的“信号”并将其拖动(单击鼠标左键并拖动)到Matplotlib图(包含一个或多个子图)。如果您引用拖动到某些数据的项目,则随附的代码可以做到这一点,并且在释放任何子图(轴)顶部的鼠标按钮时都可以完成此操作。
我要添加的内容无法解决(如果有)的解决方案,是将鼠标悬停在上方的坐标轴从列表框拖动到项目上方时,使其高亮,以使其更清楚地显示所拖动数据的位置被绘制。
我想问题是mpl_connect在按下鼠标按钮进入图形时没有“看到”来自鼠标的任何事件。有人对实现这一目标有任何想法吗?
最好的问候,丹尼尔
import tkinter as tk
import tkinter.filedialog
# import math
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
class App(tk.Tk):
def __init__(self):
self.master = tk.Tk() # This is the main canvas
self.f1 = tk.Frame(self.master, bg='lightgreen')
self.f1.grid(row = 0, column = 0, sticky= 'NSEW')
self.f2 = tk.Frame(self.f1, bg='blue')
self.f2.grid(row = 1, column = 0)
self.l1 = tk.Listbox(self.master, selectmode="extended", font = 12)
self.l1.grid(row=0, column=0, columnspan = 2, sticky='NSEW')
for item in ["one", "two", "three", "four"]:
self.l1.insert(tk.END, item)
self.master.grid_rowconfigure(0, weight=0)
self.master.grid_rowconfigure(1, weight=1)
self.master.grid_columnconfigure(0, weight=1)
self.master.grid_columnconfigure(1, weight=1)
self.canvas = tk.Canvas(self.master, bg = 'pink')
self.canvas.grid(row=1, column=0, columnspan = 2, sticky='NSEW')
self.figure = plt.figure(dpi=100, figsize=(8, 5.8))
self.figure.patch.set_facecolor('lightblue')
self.figAgg = FigureCanvasTkAgg(self.figure, self.canvas)
self.mplCanvas = self.figAgg.get_tk_widget()
self.toolbar = NavigationToolbar2Tk(self.figAgg,self.canvas)
self.toolbar.update()
self.cwid = self.canvas.create_window(0, 0, window=self.mplCanvas, anchor='nw')
self.axes = self.figure.subplots(2, 1, squeeze=True)
self.figure.tight_layout()
self.l1.bind("<ButtonPress-1>", self.StartMove, add = '+')
self.l1.bind("<ButtonPress-1>", self.showtip, add = '+')
self.l1.bind("<ButtonRelease>", self.hidetip, add = '+')
self.l1.bind("<B1-Motion>", self.OnMotion, add = '+')
self.d2 = self.figAgg.mpl_connect('axes_enter_event', self.enter_axes)
self.d3 = self.figAgg.mpl_connect('axes_leave_event', self.leave_axes)
# self.d4 = self.figAgg.mpl_connect('motion_notify_event', self.on_drop)
self.current_widget = None
self.master.bind_all("<B1-Motion>", self.show_info, add = '+')
self.mplCanvas.bind("<<B1-Enter>>", self.on_enter)
self.mplCanvas.bind("<<B1-Leave>>", self.on_leave)
self.figAgg.mpl_connect('button_release_event', self.on_drop)
def on_drop(self, event):
print('DROPPING')
def show_info(self, event):
widget = event.widget.winfo_containing(event.x_root, event.y_root)
if self.current_widget != widget:
if self.current_widget:
if widget.bindtags()[1] == 'Canvas':
print('YES A CANVAS')
self.current_widget.event_generate("<<B1-Leave>>")
self.current_widget = widget
self.current_widget.event_generate("<<B1-Enter>>")
def on_enter(self, event):
print('ENTERING')
def on_leave(self, event):
print('LEAVING')
def enter_axes(self, event):
print('enter_axes', event.inaxes)
event.inaxes.patch.set_facecolor('pink')
event.canvas.draw()
def leave_axes(self, event):
print('leave_axes', event.inaxes)
event.inaxes.patch.set_facecolor('white')
event.canvas.draw()
def StartMove(self, event):
self.x = event.widget.winfo_rootx()
self.y = event.widget.winfo_rooty()
def on_drop(self, event):
print('DROPPING')
def showtip(self, event):
self.curIndex = event.widget.nearest(event.y)
self.curIndex = event.widget.nearest(event.y)
i = event.widget.nearest(event.y)
self.curState = event.widget.selection_includes(i)
x, y, cx, cy = event.widget.bbox('active')
x += event.widget.winfo_rootx() + 25
y += event.widget.winfo_rooty() + 20
# creates a toplevel window
self.tw = tk.Toplevel(event.widget)
# Leaves only the label and removes the app window
self.tw.wm_overrideredirect(True)
self.tw.wm_geometry("+%d+%d" % (x, y))
text = '\n'.join([str(case) for case in event.widget.curselection()])
print(text)
label = tk.Label(self.tw, text=text, justify='left',
background="#ffffe0", relief='solid', borderwidth=1,
font=("tahoma", "12", "normal"),
wraplength = 180)
label.pack(ipadx=1)
def hidetip(self, event):
tw = self.tw
self.tw= None
if tw:
tw.destroy()
def OnMotion(self, event):
deltax = event.x + self.x + 25
deltay = event.y + self.y + 20
self.tw.geometry("+%d+%d" % (deltax, deltay))
app=App()
app.master.wm_geometry("800x800")
app.master.resizable(width=False, height=False)
app.master.mainloop()