关于这个Matplotlib示例,它绘制了可拖动矩形(链接),我尝试使用多边形实现相同的功能。
到目前为止,我能够在画布上绘制一个多边形并将其拖动到某个位置。但如果我松开鼠标按钮,就无法再次移动多边形,这是我的问题所在。我想通过每次按下鼠标来拖放多边形,任意次数。
我还注意到,在移动多边形后,我仍然可以单击多边形原来的位置并再次将其拖动。因此,初始的
如果我想第二次拖动该多边形,它会自动跳回到其初始位置。
到目前为止,我能够在画布上绘制一个多边形并将其拖动到某个位置。但如果我松开鼠标按钮,就无法再次移动多边形,这是我的问题所在。我想通过每次按下鼠标来拖放多边形,任意次数。
我还注意到,在移动多边形后,我仍然可以单击多边形原来的位置并再次将其拖动。因此,初始的
geometry
必须被保存在某个地方,但我认为它应该被覆盖。
编辑: 如下面的评论建议的那样,我会添加修补程序,而不是集合,因为我只会绘制一个多边形(参见旧代码中的注释)。此外,我关闭了多边形,以演示您只能通过单击多边形内部而不是边缘来拖动修补程序。如果我想第二次拖动该多边形,它会自动跳回到其初始位置。
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
#from matplotlib.collections import PatchCollection
class DraggablePolygon:
lock = None
def __init__(self, polygon):
self.poly = polygon
self.press = None
def connect(self):
'connect to all the events we need'
self.cidpress = self.poly.figure.canvas.mpl_connect(
'button_press_event', self.on_press)
self.cidrelease = self.poly.figure.canvas.mpl_connect(
'button_release_event', self.on_release)
self.cidmotion = self.poly.figure.canvas.mpl_connect(
'motion_notify_event', self.on_motion)
def on_press(self, event):
'on button press we will see if the mouse is over us and store some data'
if event.inaxes != self.poly.axes: return
if DraggablePolygon.lock is not None: return
contains, attrd = self.poly.contains(event)
if not contains: return
x0, y0 = geometry[0]
self.press = x0, y0, event.xdata, event.ydata
DraggablePolygon.lock = self
def on_motion(self, event):
'on motion we will move the rect if the mouse is over us'
if DraggablePolygon.lock is not self:
return
if event.inaxes != self.poly.axes: return
x0, y0, xpress, ypress = self.press
dx = event.xdata - xpress
dy = event.ydata - ypress
xdx = [i+dx for i,_ in geometry]
ydy = [i+dy for _,i in geometry]
self.newGeometry = [[a, b] for a, b in zip(xdx, ydy)]
#polygon = Polygon(self.newGeometry, closed=False, fill=False, linewidth=3, color='#F97306')
#patches = []
#patches.append(polygon)
#plt.cla()
#p = PatchCollection(patches, match_original=True)
#ax.add_collection(p)
self.poly.set_xy(newGeometry) # this will set the vertices of the polygon
self.poly.figure.canvas.draw()
def on_release(self, event):
'on release we reset the press data'
if DraggablePolygon.lock is not self:
return
self.press = None
DraggablePolygon.lock = None
def disconnect(self):
'disconnect all the stored connection ids'
self.poly.figure.canvas.mpl_disconnect(self.cidpress)
self.poly.figure.canvas.mpl_disconnect(self.cidrelease)
self.poly.figure.canvas.mpl_disconnect(self.cidmotion)
fig = plt.figure()
ax = fig.add_subplot(111)
geometry = [[0.0,0.0],[0.1,0.05],[0.2,0.15],[0.3,0.20],[0.4,0.25],[0.5,0.30],
[0.6,0.25],[0.7,0.15],[0.8,0.05],[0.9,0.025],[1.0,0.0]]
patches = []
polygon = plt.Polygon(geometry, closed=True, fill=False, linewidth=3, color='#F97306')
#patches.append(polygon)
#p = PatchCollection(patches, match_original=True)
#ax.add_collection(p)
ax.add_patch(polygon)
dp = DraggablePolygon(polygon)
dp.connect()
plt.show()
我认为geometry
和newGeometry
的定义必须位于代码中不同的位置,但经过几次尝试后,我无法找到一个可行的解决方案。有人能找到我犯的错误吗?
rect.set_x
,但是这在多边形中不存在。相反,您需要通过polygon.set_xy
一次性设置所有顶点。 - ImportanceOfBeingErneston_press
中调用了geometry
而不是newGeometry
... - Philippgeometry
没有在类内定义,因此它将始终保持初始位置。 - ImportanceOfBeingErnest