python - 可拖动线在 Matplotlib 中相互选择

标签 python matplotlib event-handling drag lines

我正在尝试使用 matplotlib 处理和拾取创建一类可拖动线。目的是在图形上设置不同的阈值和间隔。这是代码:

import matplotlib.pyplot as plt
import matplotlib.lines as lines
import numpy as np

class draggable_lines:

    def __init__(self, ax, kind, XorY):

        self.ax = ax
        self.c = ax.get_figure().canvas
        self.o = kind
        self.XorY = XorY

        if kind == "h":
            x = [-1, 1]
            y = [XorY, XorY]

        elif kind == "v":
            x = [XorY, XorY]
            y = [-1, 1]

        else:
            print("choose h or v line")

        self.line = lines.Line2D(x, y, picker=5)
        self.ax.add_line(self.line)
        self.c.draw()
        sid = self.c.mpl_connect('pick_event', self.clickonline)

    # pick line when I select it 
    def clickonline(self, event):

        self.active_line = event.artist
        print("line selected ", event.artist)
        self.follower = self.c.mpl_connect("motion_notify_event", self.followmouse)
        self.releaser = self.c.mpl_connect("button_press_event", self.releaseonclick)

    # The selected line must follow the mouse
    def followmouse(self, event):

        if self.o == "h":
            self.line.set_ydata([event.ydata, event.ydata])
        else:
            self.line.set_xdata([event.xdata, event.xdata])

        self.c.draw()

    # release line on click
    def releaseonclick(self, event):

        if self.o == "h":
            self.XorY = self.line.get_ydata()[0]
        else:
            self.XorY = self.line.get_xdata()[0]

        print (self.XorY)

        self.c.mpl_disconnect(self.releaser)
        self.c.mpl_disconnect(self.follower)


plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111)
Vline = draggable_lines(ax, "h", 0.5)
Tline = draggable_lines(ax, "v", 0.5)
Tline2 = draggable_lines(ax, "v", 0.1)

该行为是我仅使用 1 行时的预期(即使它在我释放行时也通知选择)。

当我使用多条线时,它会同时选择所有线!

我想我误解了事件管理器的功能,但我不明白为什么不同的对象,区分得很好(正如我在 print("line selected ", event.artist) 中看到的那样)应该选择自己和另一个!

最佳答案

有人可能会问不同的问题:如果您点击其中任何一条线,matplotlib 如何知道要拖动哪条线?答:不会,因为它有三个回调,每行一个,并且会全部执行。

因此,解决方案是首先检查点击的行是否实际上是要在 'pick_event' 回调中移动的行:

if event.artist == self.line:
    # register other callbacks

(换句话说:如果不经常调用 canvas.draw(),而是调用 canvas.draw_idle())

import matplotlib.pyplot as plt
import matplotlib.lines as lines

class draggable_lines:
    def __init__(self, ax, kind, XorY):
        self.ax = ax
        self.c = ax.get_figure().canvas
        self.o = kind
        self.XorY = XorY

        if kind == "h":
            x = [-1, 1]
            y = [XorY, XorY]

        elif kind == "v":
            x = [XorY, XorY]
            y = [-1, 1]
        self.line = lines.Line2D(x, y, picker=5)
        self.ax.add_line(self.line)
        self.c.draw_idle()
        self.sid = self.c.mpl_connect('pick_event', self.clickonline)

    def clickonline(self, event):
        if event.artist == self.line:
            print("line selected ", event.artist)
            self.follower = self.c.mpl_connect("motion_notify_event", self.followmouse)
            self.releaser = self.c.mpl_connect("button_press_event", self.releaseonclick)

    def followmouse(self, event):
        if self.o == "h":
            self.line.set_ydata([event.ydata, event.ydata])
        else:
            self.line.set_xdata([event.xdata, event.xdata])
        self.c.draw_idle()

    def releaseonclick(self, event):
        if self.o == "h":
            self.XorY = self.line.get_ydata()[0]
        else:
            self.XorY = self.line.get_xdata()[0]

        print (self.XorY)

        self.c.mpl_disconnect(self.releaser)
        self.c.mpl_disconnect(self.follower)

fig = plt.figure()
ax = fig.add_subplot(111)
Vline = draggable_lines(ax, "h", 0.5)
Tline = draggable_lines(ax, "v", 0.5)
Tline2 = draggable_lines(ax, "v", 0.1)
plt.show()

enter image description here

关于python - 可拖动线在 Matplotlib 中相互选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47439355/

相关文章:

javascript - 使用 CKEDITOR.config.on 定义事件处理程序的优先级

c# - 后台人员总是很忙

javascript - 如何强制 Canvas 事件处理程序完成更新

python - 在 Python 中打印缓慢但不截断单词

Python Matplotlib 绘图 : Set aspect ratio of output file (e. g。图片)

Python 2 和 IPv6

python - Matplotlib 以奇数间隔日期 YearLocator

python - (hist, bin_edges) 列表的 3d 图,其中直方图条形图或线条位于 z-y 平面

python - 将数据帧转换为没有列名的嵌套字典

javascript - 将RSA加密的JavaScript代码翻译为Python