2010-03-29 15 views
37

Tôi đang vẽ chú thích trên đối tượng trục trong matplotlib nhưng vị trí mặc định xác nhận đặt nó ở vị trí thông minh dường như không hoạt động. Lý tưởng nhất, tôi muốn có truyền thuyết có thể kéo được bởi người dùng. Điều này có thể giải quyết như thế nào?Cách tạo chú thích có thể kéo trong matplotlib?

+0

Adam: cho rằng điều này là đáng kể, toàn diện và đủ liên quan để đưa vào bản phân phối Matplotlib và cho rằng (tôi nghĩ) bạn đã xóa Câu hỏi ban đầu của mình, bạn có nhớ thêm một vài câu ở trên cùng không của Q này để người dùng có thể có được ý tưởng về mã này là gì (để lưu chúng khỏi phải đọc chính mã đó). Và công việc tốt đẹp, bằng cách +1 từ tôi. – doug

+0

Cảm ơn doug. Tôi phrased câu hỏi ở đầu như bạn đề nghị. Hy vọng rằng điều này sẽ hữu ích. :] –

+0

điều này có thể được mở rộng cho trục phụ? – denfromufa

Trả lời

28

Lưu ý: Điều này bây giờ được xây dựng vào matplotlib

leg = plt.legend() 
if leg: 
    leg.draggable() 

sẽ làm việc như mong đợi


Vâng, tôi thấy bit và miếng của giải pháp rải rác giữa các danh sách gửi thư. Tôi đã đưa ra một đoạn mô-đun đẹp mã mà bạn có thể thả vào và sử dụng ... ở đây là:

class DraggableLegend: 
    def __init__(self, legend): 
     self.legend = legend 
     self.gotLegend = False 
     legend.figure.canvas.mpl_connect('motion_notify_event', self.on_motion) 
     legend.figure.canvas.mpl_connect('pick_event', self.on_pick) 
     legend.figure.canvas.mpl_connect('button_release_event', self.on_release) 
     legend.set_picker(self.my_legend_picker) 

    def on_motion(self, evt): 
     if self.gotLegend: 
      dx = evt.x - self.mouse_x 
      dy = evt.y - self.mouse_y 
      loc_in_canvas = self.legend_x + dx, self.legend_y + dy 
      loc_in_norm_axes = self.legend.parent.transAxes.inverted().transform_point(loc_in_canvas) 
      self.legend._loc = tuple(loc_in_norm_axes) 
      self.legend.figure.canvas.draw() 

    def my_legend_picker(self, legend, evt): 
     return self.legend.legendPatch.contains(evt) 

    def on_pick(self, evt): 
     if evt.artist == self.legend: 
      bbox = self.legend.get_window_extent() 
      self.mouse_x = evt.mouseevent.x 
      self.mouse_y = evt.mouseevent.y 
      self.legend_x = bbox.xmin 
      self.legend_y = bbox.ymin 
      self.gotLegend = 1 

    def on_release(self, event): 
     if self.gotLegend: 
      self.gotLegend = False 

... và trong mã của bạn ...

def draw(self): 
    ax = self.figure.add_subplot(111) 
    scatter = ax.scatter(np.random.randn(100), np.random.randn(100)) 


legend = DraggableLegend(ax.legend()) 

Tôi gửi email cho nhóm người dùng Matplotlib và John Hunter đã tử tế để thêm giải pháp của tôi vào SVN HEAD.

On Thu, 28 Tháng 1 2010 lúc 3:02 PM, Adam Fraser đã viết:

tôi nghĩ rằng tôi muốn chia sẻ một giải pháp cho vấn đề huyền thoại kéo từ nó đã cho tôi mãi mãi để đồng hóa tất cả kiến ​​thức phân tán trên danh sách gửi thư ...

Ví dụ hay - tuyệt. Tôi đã thêm mã vào legend.py. Bây giờ bạn có thể làm

chân = ax.legend()
leg.draggable()

để kích hoạt chế độ kéo. Bạn có thể nhiều lần gọi func này để chuyển đổi trạng thái có thể kéo .

Tôi hy vọng điều này hữu ích cho những người làm việc với matplotlib.

13

Trong các phiên bản mới hơn của Matplotlib (v1.0.1), tính năng này được tích hợp sẵn.

def draw(self): 
    ax = self.figure.add_subplot(111) 
    scatter = ax.scatter(np.random.randn(100), np.random.randn(100)) 
    legend = ax.legend() 
    legend.draggable(state=True) 

Nếu bạn đang sử dụng matplotlib tương tác (ví dụ: trong chế độ pylab của IPython).

plot(range(10), range(10), label="test label") 
plot(range(10), [5 for x in range(10)], label="another test") 
l = legend() 
l.draggable(True)