当前位置: 首页 > 面试题库 >

Matplotlib交互式拖动重叠点

邢晗日
2023-03-14
问题内容

就我而言,每次只想拖一个点。但是,由于两个点严重重叠,因此拖动一个点将导致另一个点被拖动。我如何只拖动上面的点?谢谢!

from pylab import *
from scipy import *
import matplotlib.pyplot as plt
import matplotlib.patches as patches


class DraggablePoint:
    def __init__(self, p):
        self.point = p
        self.press = None

    def connect(self):
        self.cidpress = self.point.figure.canvas.mpl_connect('button_press_event', self.button_press_event)
        self.cidrelease = self.point.figure.canvas.mpl_connect('button_release_event', self.button_release_event)
        self.cidmotion = self.point.figure.canvas.mpl_connect('motion_notify_event', self.motion_notify_event)

    def disconnect(self):
    'disconnect all the stored connection ids'
        self.point.figure.canvas.mpl_disconnect(self.cidpress)
        self.point.figure.canvas.mpl_disconnect(self.cidrelease)
        self.point.figure.canvas.mpl_disconnect(self.cidmotion)


    def button_press_event(self,event):
        if event.inaxes != self.point.axes:
            return
        contains = self.point.contains(event)[0]
        if not contains: return
        self.press = self.point.center, event.xdata, event.ydata


    def button_release_event(self,event):
        self.press = None
        self.point.figure.canvas.draw()

    def motion_notify_event(self, event):
        if self.press is None: return
        if event.inaxes != self.point.axes: return
        self.point.center, xpress, ypress = self.press
        dx = event.xdata - xpress
        dy = event.ydata - ypress 
        self.point.center = (self.point.center[0]+dx, self.point.center[1]+dy)
        print self.point.center
        self.point.figure.canvas.draw()

if __name__ == '__main__':
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.set_xlim(-1,2)
    ax.set_ylim(-1,2)
    circles = []
    circle1 = patches.Circle((0.32,0.3), 0.2, fc='r', alpha=0.5, picker=True)
    circle = patches.Circle((0.3,0.3), 0.2, fc='b', alpha=0.5, picker=True)
    circles.append(ax.add_patch(circle1))
    circles.append(ax.add_patch(circle))
    drs = []
    for c in circles:
        #print c.center[0]    
        dr = DraggablePoint(c)
        dr.connect()   
        drs.append(dr) 
    plt.show()

问题答案:

Joe的方法工作正常,但是它使一组可拖动点作为一个类,而不是单个可拖动点类。我只是遇到了一种使用动画blit技术解决上述问题的替代方法。它不仅使拖动更快,更流畅,而且只能拖动一个点。请参阅以下代码

import matplotlib.pyplot as plt
import matplotlib.patches as patches
class DraggablePoint:
    lock = None #only one can be animated at a time
    def __init__(self, point):
        self.point = point
        self.press = None
        self.background = None

    def connect(self):
        'connect to all the events we need'
        self.cidpress = self.point.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.cidrelease = self.point.figure.canvas.mpl_connect('button_release_event', self.on_release)
        self.cidmotion = self.point.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)

    def on_press(self, event):
        if event.inaxes != self.point.axes: return
        if DraggablePoint.lock is not None: return
        contains, attrd = self.point.contains(event)
        if not contains: return
        self.press = (self.point.center), event.xdata, event.ydata
        DraggablePoint.lock = self

        # draw everything but the selected rectangle and store the pixel buffer
        canvas = self.point.figure.canvas
        axes = self.point.axes
        self.point.set_animated(True)
        canvas.draw()
        self.background = canvas.copy_from_bbox(self.point.axes.bbox)

        # now redraw just the rectangle
        axes.draw_artist(self.point)

        # and blit just the redrawn area
        canvas.blit(axes.bbox)

    def on_motion(self, event):
        if DraggablePoint.lock is not self:
            return
        if event.inaxes != self.point.axes: return
        self.point.center, xpress, ypress = self.press
        dx = event.xdata - xpress
        dy = event.ydata - ypress
        self.point.center = (self.point.center[0]+dx, self.point.center[1]+dy)

        canvas = self.point.figure.canvas
        axes = self.point.axes
        # restore the background region
        canvas.restore_region(self.background)

        # redraw just the current rectangle
        axes.draw_artist(self.point)

        # blit just the redrawn area
        canvas.blit(axes.bbox)

    def on_release(self, event):
        'on release we reset the press data'
        if DraggablePoint.lock is not self:
            return

        self.press = None
        DraggablePoint.lock = None

        # turn off the rect animation property and reset the background
        self.point.set_animated(False)
        self.background = None

        # redraw the full figure
        self.point.figure.canvas.draw()

    def disconnect(self):
        'disconnect all the stored connection ids'
        self.point.figure.canvas.mpl_disconnect(self.cidpress)
        self.point.figure.canvas.mpl_disconnect(self.cidrelease)
        self.point.figure.canvas.mpl_disconnect(self.cidmotion)

fig = plt.figure()
ax = fig.add_subplot(111)
drs = []
circles = [patches.Circle((0.32, 0.3), 0.03, fc='r', alpha=0.5),
               patches.Circle((0.3,0.3), 0.03, fc='g', alpha=0.5)]

for circ in circles:
    ax.add_patch(circ)
    dr = DraggablePoint(circ)
    dr.connect()
    drs.append(dr)

plt.show()


 类似资料:
  • 响应式交互能让用户信任,并且吸引他们。 当用户操作一个美观且符合常理的应用时,他们会感到满意甚至很高兴。那是一种经过深思熟虑、有目的、非随机的而且可以带有轻微异想天开但不会让人分心的交互。 在 material design 中,应用是响应式的并且渴望用户操作的: 触摸,语音,键盘及鼠标作为首要考虑的输入方式。 虽然 UI 元素是有形的,但是他们被限制在屏幕里面(电脑或者移动设备的屏幕),视觉元素

  • 原文:Using matplotlib in a python shell 警告 该页面的内容已严重过时。 默认情况下,matplotlib 将绘图延迟到脚本结束,因为绘图可能是开销大的操作,并且你可能不想在每次更改单个属性时更新绘图,而是只在所有属性更改后更新一次。 但是在 python shell 中工作时,通常需要用每个命令更新绘图,例如,在更改xlabel()或一行的标记样式之后。 虽然这

  • 原文:Interactive navigation 所有图形窗口都带有导航工具栏,可用于浏览数据集。 以下是工具栏底部的每个按钮的说明: Home(首页)、Forward(前进)和Back(后退)按钮: 这些类似于 Web 浏览器的前进和后退按钮。 它们用于在之前定义的视图之间来回浏览。 它们没有意义,除非你已经使用平移和缩放按钮访问了其他地方。 这类似于尝试在访问新页面之前单击 Web 浏览器上

  • 我曾尝试在VisualStudio2008中设置Interactive Broker的C API,但我知道的C非常有限,并且不断出现错误: 1)是否有任何方法可以使用某种轻量级的脚本语言来连接到Interactive Brokers并进行交易。 像Python这样轻量级的东西就可以了,是的,我已经研究过IBMY,但我不明白java2python系统是如何工作的。 2) 您是如何设置您的自动系统的,

  • 问题内容: Matplotlib的pyplot中的“​​交互模式”文档如下: pyplot界面的交互属性控制是否在每个pyplot命令上绘制图形画布。如果interactive为False,则在每个绘图命令上都会更新图形状态,但只会在显式调用draw()时绘制图形状态。当Interactive为True时,每个pyplot命令都会触发一次绘制。 这似乎很清楚:启用交互模式后,无需执行即可执行操作。

  • 你亦可以选择进行交互式的rebase。这种方法通常用于在向别处推送提交之前对它们进行重写。交互式rebase提供了一个简单易用的途径让你在和别人分享提交之前对你的提交进行分割、合并或者重排序。在把从其他开发者处拉取的提交应用到本地时,你也可以使用交互式rebase对它们进行清理。 如果你想在rebase的过程中对一部分提交进行修改,你可以在'git rebase'命令中加入'-i'或'--inte