区分button_press_event与matplotlib中的拖动和缩放单击

Gab*_*iel 4 python matplotlib

我有一个简单的代码,其中显示了两个子图,并允许用户在记录x,y这些点击的坐标时在第二个子图上单击鼠标左键。

问题在于,单击以选择要缩放的区域并拖动子图的单击也被标识为左键单击。

有没有办法区分和过滤掉这些左击?

import numpy as np
import matplotlib.pyplot as plt


def onclick(event, ax):
    # Only clicks inside this axis are valid.
    if event.inaxes == ax:
        if event.button == 1:
            print(event.xdata, event.ydata)
            # Draw the click just made
            ax.scatter(event.xdata, event.ydata)
            ax.figure.canvas.draw()
        elif event.button == 2:
            # Do nothing
            print("scroll click")
        elif event.button == 3:
            # Do nothing
            print("right click")
        else:
            pass


fig, (ax1, ax2) = plt.subplots(1, 2)
# Plot some random scatter data
ax2.scatter(np.random.uniform(0., 10., 10), np.random.uniform(0., 10., 10))

fig.canvas.mpl_connect(
    'button_press_event', lambda event: onclick(event, ax2))
plt.show()
Run Code Online (Sandbox Code Playgroud)

Imp*_*est 9

您可以检查在先前移动鼠标后是否释放了鼠标按钮。由于要进行缩放和平移,因此只有在没有以前的移动发生时,才可以调用该函数以绘制新点。

import numpy as np
import matplotlib.pyplot as plt

class Click():
    def __init__(self, ax, func, button=1):
        self.ax=ax
        self.func=func
        self.button=button
        self.press=False
        self.move = False
        self.c1=self.ax.figure.canvas.mpl_connect('button_press_event', self.onpress)
        self.c2=self.ax.figure.canvas.mpl_connect('button_release_event', self.onrelease)
        self.c3=self.ax.figure.canvas.mpl_connect('motion_notify_event', self.onmove)

    def onclick(self,event):
        if event.inaxes == self.ax:
            if event.button == self.button:
                self.func(event, self.ax)
    def onpress(self,event):
        self.press=True
    def onmove(self,event):
        if self.press:
            self.move=True
    def onrelease(self,event):
        if self.press and not self.move:
            self.onclick(event)
        self.press=False; self.move=False


def func(event, ax):
    print(event.xdata, event.ydata)
    ax.scatter(event.xdata, event.ydata)
    ax.figure.canvas.draw()

fig, (ax1, ax2) = plt.subplots(1, 2)
# Plot some random scatter data
ax2.scatter(np.random.uniform(0., 10., 10), np.random.uniform(0., 10., 10))
click = Click(ax2, func, button=1)
plt.show()
Run Code Online (Sandbox Code Playgroud)


小智 7

我意识到这是一个老问题,但我也遇到了同样的问题,我想我找到了一个巧妙的解决方案;然而它目前仅适用于 Qt 后端(其他后端也可能存在类似的解决方案)。这个想法是 matplotlib 在缩放或平移时改变光标形状,因此您可以检查这一点。这是改编后的代码:

import numpy as np
import matplotlib
matplotlib.use('qt5agg')
import matplotlib.pyplot as plt


def onclick(event, ax):
    # Only clicks inside this axis are valid.
    try: # use try/except in case we are not using Qt backend
        zooming_panning = ( fig.canvas.cursor().shape() != 0 ) # 0 is the arrow, which means we are not zooming or panning.
    except:
        zooming_panning = False
    if zooming_panning: 
        print("Zooming or panning")
        return
    if event.inaxes == ax:
        if event.button == 1:
            print(event.xdata, event.ydata)
            # Draw the click just made
            ax.scatter(event.xdata, event.ydata)
            ax.figure.canvas.draw()
        elif event.button == 2:
            # Do nothing
            print("scroll click")
        elif event.button == 3:
            # Do nothing
            print("right click")
        else:
            pass


fig, (ax1, ax2) = plt.subplots(1, 2)
# Plot some random scatter data
ax2.scatter(np.random.uniform(0., 10., 10), np.random.uniform(0., 10., 10))

fig.canvas.mpl_connect(
    'button_press_event', lambda event: onclick(event, ax2))
plt.show()

Run Code Online (Sandbox Code Playgroud)