Hom*_*lli 15 python matplotlib
我想使用matplotlib执行以下操作:
通过执行以下操作在两点之间创建一条线:i.使用"左"按钮双击画布(第一个创建的点)ii.将鼠标拖动到(或简单地点击)第二点ii.在第一点和第二点之间绘制线
通过执行以下操作,在画布上放置绿色(或任何其他颜色)圆圈:i.双击画布,使用向右按钮
由于双击时我可能会犯错,我希望能够选择绘制的圆(或线),然后按删除按钮删除所选项.
回到VB的美好时光,这是一个15分钟的工作.在浪费了几个小时之后,我已经没有想法了.
这是我到目前为止:
import matplotlib.pyplot as plt
class LineDrawer(object):
lines = []
def draw_line(self):
ax = plt.gca()
xy = plt.ginput(2)
x = [p[0] for p in xy]
y = [p[1] for p in xy]
line = plt.plot(x,y)
ax.figure.canvas.draw()
self.lines.append(line)
def onclick(event):
if event.dblclick:
if event.button == 1:
# Draw line
ld = LineDrawer()
ld.draw_line() # here you click on the plot
elif event.button == 3:
# Write to figure
plt.figtext(3, 8, 'boxed italics text in data coords', style='italic', bbox={'facecolor':'red', 'alpha':0.5, 'pad':10})
circ = plt.Circle((event.x, event.y), radius=0.07, color='g')
ax.add_patch(circ)
plt.draw()
else:
pass # Do nothing
def onpick(event):
thisline = event.artist
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()
ind = event.ind
print ('onpick points:', zip(xdata[ind], ydata[ind]))
fig, ax = plt.subplots()
connection_id = fig.canvas.mpl_connect('button_press_event', onclick)
fig.canvas.mpl_connect('pick_event', onpick)
plt.tight_layout()
plt.show()
Run Code Online (Sandbox Code Playgroud)
除了删除功能,我还没有完成,为什么我的代码不执行要求1和2?
我做错了什么?更重要的是,我如何修复代码以获得所需的功能?
J R*_*ape 16
你几乎就在那里,但你的逻辑发送代码在双击上绘制一条线而不存储双击的位置,因此它需要两次单击来绘制一条线.此外,您需要在圆形代码中绘制画布.这是一个执行要求1和2的最低限度修订版本:
import matplotlib.pyplot as plt
class LineDrawer(object):
lines = []
def draw_line(self, startx,starty):
ax = plt.gca()
xy = plt.ginput(1)
x = [startx,xy[0][0]]
y = [starty,xy[0][1]]
line = plt.plot(x,y)
ax.figure.canvas.draw()
self.lines.append(line)
def onclick(event):
if event.dblclick:
if event.button == 1:
# Draw line
ld = LineDrawer()
ld.draw_line(event.xdata,event.ydata) # here you click on the plot
elif event.button == 3:
# Write to figure
plt.figtext(3, 8, 'boxed italics text in data coords', style='italic', bbox={'facecolor':'red', 'alpha':0.5, 'pad':10})
circ = plt.Circle((event.xdata, event.ydata), radius=0.07, color='g')
ax.add_patch(circ)
ax.figure.canvas.draw()
else:
pass # Do nothing
def onpick(event):
thisline = event.artist
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()
ind = event.ind
print ('onpick points:', zip(xdata[ind], ydata[ind]))
fig, ax = plt.subplots()
connection_id = fig.canvas.mpl_connect('button_press_event', onclick)
fig.canvas.mpl_connect('pick_event', onpick)
plt.tight_layout()
plt.show()
Run Code Online (Sandbox Code Playgroud)
请注意,matplotlib可能不是实现这些要求的最佳或最简单的方法 - 轴也会在绘制第一行时自动重新缩放.您可以通过修复xlim和更改此设置ylim.例如如下:
ax.set_xlim([0,2])
ax.set_ylim([0,2])
Run Code Online (Sandbox Code Playgroud)
要实现需求3,您将必须存储拾取的对象并侦听按键匹配删除以删除它.这是一个结合了以上所有内容的版本.我尽可能地坚持你的设计.我将对相关轴对象中的拾取对象的引用存储起来.如果您不想将拾取的对象插入当前轴,则可能需要实现自己的数据结构来存储拾取的对象.我已经测试了一下,但可能有点击/按键序列可能会混淆逻辑.
import matplotlib.pyplot as plt
# function to draw lines - from matplotlib examples. Note you don't need
# to keep a reference to the lines drawn, so I've removed the class as it
# is overkill for your purposes
def draw_line(startx,starty):
ax = plt.gca()
xy = plt.ginput(1)
x = [startx,xy[0][0]]
y = [starty,xy[0][1]]
line = ax.plot(x,y, picker=5) # note that picker=5 means a click within 5 pixels will "pick" the Line2D object
ax.figure.canvas.draw()
def onclick(event):
"""
This implements click functionality. If it's a double click do something,
else ignore.
Once in the double click block, if its a left click, wait for a further
click and draw a line between the double click co-ordinates and that click
(using ginput(1) - the 1 means wait for one mouse input - a higher number
is used to get multiple clicks to define a polyline)
If the double click was a right click, draw the fixed radius circle
"""
if event.dblclick:
if event.button == 1:
# Draw line
draw_line(event.xdata,event.ydata) # here you click on the plot
elif event.button == 3:
# Write to figure
plt.figtext(3, 8, 'boxed italics text in data coords', style='italic', bbox={'facecolor':'red', 'alpha':0.5, 'pad':10})
circ = plt.Circle((event.xdata, event.ydata), radius=0.07, color='g', picker = True)
ax.add_patch(circ)
ax.figure.canvas.draw()
else:
pass # Do nothing
def onpick(event):
"""
Handles the pick event - if an object has been picked, store a
reference to it. We do this by simply adding a reference to it
named 'stored_pick' to the axes object. Note that in python we
can dynamically add an attribute variable (stored_pick) to an
existing object - even one that is produced by a library as in this
case
"""
this_artist = event.artist #the picked object is available as event.artist
# print(this_artist) #For debug just to show you which object is picked
plt.gca().picked_object = this_artist
def on_key(event):
"""
Function to be bound to the key press event
If the key pressed is delete and there is a picked object,
remove that object from the canvas
"""
if event.key == u'delete':
ax = plt.gca()
if ax.picked_object:
ax.picked_object.remove()
ax.picked_object = None
ax.figure.canvas.draw()
fig, ax = plt.subplots()
#First we need to catch three types of event, clicks, "picks" (a specialised
#type of click to select an object on a matplotlib canvas) and key presses.
#The logic is - if it's a right double click, wait for the next click and draw
#a line, if its a right double click draw a fixed radius circle. If it's a
#pick, store a reference to the picked item until the next keypress. If it's
#a keypress - test if it's delete and if so, remove the picked object.
#The functions (defined above) bound to the events implement this logic
connection_id = fig.canvas.mpl_connect('button_press_event', onclick)
fig.canvas.mpl_connect('pick_event', onpick)
cid = fig.canvas.mpl_connect('key_press_event', on_key)
#set the size of the matplotlib figure in data units, so that it doesn't
#auto-resize (which it will be default on the first drawn item)
ax.set_xlim([0,2])
ax.set_ylim([0,2])
ax.aspect = 1
plt.tight_layout()
plt.show()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11495 次 |
| 最近记录: |