我想同时:
1)通过window-select在matplotlib画布上选择多个艺术家。
我的意思是,如果我按住鼠标按钮,拖动鼠标, 并释放,由x,y位置定义的矩形中的所有艺术家 按下按钮和按钮释放。
2)拖动多个选定的艺术家,然后向下按鼠标 选定的艺术家之一,移动鼠标,并释放。
这与普通文件浏览器中的预期完全相同。
为此,我已经开始编写两个类<script>
var xhr = new XMLHttpRequest();
var url = "http://example.api.com/path/etc/etc/";
xhr.open("POST", url, true);
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-type", "application/json");
xhr.setRequestHeader("custom-header-1", "foo");
xhr.setRequestHeader("custom-header-2", "bla");
xhr.send(requ);
//...
</script>
和。{
WindowSelect
,如下所示。
Draggable
实现了(1)的逻辑
不知道如何手动触发选择器功能
matplotlib documentation中提到的。
相反,我称一个占位符函数WindowSelect
。
func
实现了(2)的逻辑
一次挑选一位艺术家(无耻地从中拣选出来
另一个表示SO回答)。 matplotlib
documentation {{3}}
表示同时挑选多位艺术家
是可能的(网页上的最后一个例子)。但是,如果我,为
例如,将选取器的公差设置得非常高,只有一个
艺术家似乎被选中/然后可以被拖动
画布,所以我不确定代码需要如何改变以适应
多位艺术家。
Draggable
答案 0 :(得分:1)
很难保持选择和拖动分开。这是因为根据您当前是选择还是拖动,各个事件需要执行不同的任务。因此,在每个时间点,您需要知道当前正在执行哪个操作,并且最好在单个类中完成,您可能在其中有两个不同的标志self.currently_selecting
和self.currently_dragging
。然后,您还需要一个选定的艺术家列表self.selected_artists
,可以在需要时拖动它们。
我会摆脱pick_event
,因为很难区分button_press_event
(它们会被同时触发,而不是先确定性的)。相反,单个button_press_event
可以处理所有逻辑;即找出艺术家是否发生了点击,如果是,则开始拖动,否则开始选择。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
class WindowSelect(object):
def __init__(self, artists):
self.artists = artists
self.colors = [a.get_facecolor() for a in self.artists]
# assume all artists are in the same figure, otherwise selection is meaningless
self.fig = self.artists[0].figure
self.ax = self.artists[0].axes
self.fig.canvas.mpl_connect('button_press_event', self.on_press)
self.fig.canvas.mpl_connect('button_release_event', self.on_release)
self.fig.canvas.mpl_connect('motion_notify_event', self.on_motion)
self.currently_selecting = False
self.currently_dragging = False
self.selected_artists = []
self.offset = np.zeros((1,2))
self.rect = plt.Rectangle((0,0),1,1, linestyle="--",
edgecolor="crimson", fill=False)
self.ax.add_patch(self.rect)
self.rect.set_visible(False)
def on_press(self, event):
# is the press over some artist
isonartist = False
for artist in self.artists:
if artist.contains(event)[0]:
isonartist = artist
self.x0 = event.xdata
self.y0 = event.ydata
if isonartist:
# add clicked artist to selection
self.select_artist(isonartist)
# start dragging
self.currently_dragging = True
ac = np.array([a.center for a in self.selected_artists])
ec = np.array([event.xdata, event.ydata])
self.offset = ac - ec
else:
#start selecting
self.currently_selecting = True
self.deseclect_artists()
def on_release(self, event):
if self.currently_selecting:
for artist in self.artists:
if self.is_inside_rect(*artist.center):
self.select_artist(artist)
self.fig.canvas.draw_idle()
self.currently_selecting = False
self.rect.set_visible(False)
elif self.currently_dragging:
self.currently_dragging = False
def on_motion(self, event):
if self.currently_dragging:
newcenters = np.array([event.xdata, event.ydata])+self.offset
for i, artist in enumerate(self.selected_artists):
artist.center = newcenters[i]
self.fig.canvas.draw_idle()
elif self.currently_selecting:
self.x1 = event.xdata
self.y1 = event.ydata
#add rectangle for selection here
self.selector_on()
self.fig.canvas.draw_idle()
def is_inside_rect(self, x, y):
xlim = np.sort([self.x0, self.x1])
ylim = np.sort([self.y0, self.y1])
if (xlim[0]<=x) and (x<xlim[1]) and (ylim[0]<=y) and (y<ylim[1]):
return True
else:
return False
def select_artist(self, artist):
artist.set_color('k')
if artist not in self.selected_artists:
self.selected_artists.append(artist)
def deseclect_artists(self):
for artist,color in zip(self.artists, self.colors):
artist.set_color(color)
self.selected_artists = []
def selector_on(self):
self.rect.set_visible(True)
xlim = np.sort([self.x0, self.x1])
ylim = np.sort([self.y0, self.y1])
self.rect.set_xy((xlim[0],ylim[0] ) )
self.rect.set_width(np.diff(xlim))
self.rect.set_height(np.diff(ylim))
def demo():
fig, ax = plt.subplots(1,1)
xlim = [-5, 5]
ylim = [-5, 5]
ax.set(xlim=xlim, ylim=ylim)
circles = [patches.Circle((3.0, 3.0), 0.5, fc='r', alpha=1.0),
patches.Circle((0.0, 0.0), 0.5, fc='b', alpha=1.0),
patches.Circle((0.0, 3.0), 0.5, fc='g', alpha=1.0)]
for circle in circles:
ax.add_patch(circle)
w = WindowSelect(circles)
plt.show()
if __name__ == '__main__':
demo()
答案 1 :(得分:0)
您的第二课程需要的唯一修改是一次跟踪和移动多个artists
。修改以下功能将允许这样做。
def on_pick(self, event):
if self.current_artist is None:
self.current_artist = event.artist
ecoord = array([event.mouseevent.xdata, event.mouseevent.ydata])
self.offsets = [a.center for a in self.artists] - ecoord
def on_motion(self, event):
if not self.currently_dragging:
return
if self.current_artist is None:
return
center = event.xdata, event.ydata
for artist, delta in zip(self.artists, self.offsets):
artist.center = center + delta
self.artists[0].figure.canvas.draw()