2016-05-25 2 views
1

Я считаю, что я неправильно использую события выбора Матплотлиба. В следующем коде я создаю три непересекающихся оранжевых диска с указанным радиусом и позицией, идентифицированной номером id.Правильное использование события выбора Matplotlib

Я хочу, чтобы один-щелкнуть по каждому из дисков и распечатать сообщение на терминал, определяющее диски, центр, радиус и идентификатор. Однако каждый раз, когда я нажимаю на диск, события выбора для все диски уволены. Где я иду не так?

Вот сюжет

enter image description here

Вот выход щелкать диск 1

enter image description here

Вот код.

from global_config import GC 
import matplotlib as mpl 
import matplotlib.pyplot as plt 
import numpy as np 


class Disk: 


    def __init__(self, center, radius, myid = None, figure=None, axes_object=None): 
     """ 
     @ARGS 
     CENTER : Tuple of floats 
     RADIUS : Float 
     """ 
     self.center = center 
     self.radius = radius 
     self.fig = figure 
     self.ax  = axes_object 
     self.myid = myid 

    def onpick(self,event): 
     print "You picked the disk ", self.myid, " with Center: ", self.center, " and Radius:", self.radius 


    def mpl_patch(self, diskcolor= 'orange'): 
     """ Return a Matplotlib patch of the object 
     """ 
     mypatch = mpl.patches.Circle(self.center, self.radius, facecolor = diskcolor, picker=1) 

     if self.fig != None: 
      self.fig.canvas.mpl_connect('pick_event', self.onpick) # Activate the object's method 

     return mypatch 



def main(): 

    fig = plt.figure() 
    ax = fig.add_subplot(111) 
    ax.set_title('click on disks to print out a message') 

    disk_list = [] 

    disk_list.append(Disk((0,0), 1.0, 1, fig, ax ) ) 
    ax.add_patch(disk_list[-1].mpl_patch()) 

    disk_list.append(Disk((3,3), 0.5, 2, fig, ax ) ) 
    ax.add_patch(disk_list[-1].mpl_patch()) 

    disk_list.append(Disk((4,9), 2.5, 3, fig, ax ) ) 
    ax.add_patch(disk_list[-1].mpl_patch()) 


    ax.set_ylim(-2, 10); 
    ax.set_xlim(-2, 10); 

    plt.show() 


if __name__ == "__main__": 
    main() 

ответ

3

Существует несколько способов решения этой проблемы. Я изменил свой код, чтобы попытаться показать два возможных способа (так что у него есть посторонний код, хотя вопрос, каким способом вы хотели бы его обработать).

Вообще-то, я думаю, вы должны были приложить только один обработчик pick_event, и этот обработчик должен был бы определить, какой объект был поражен. Приведенный ниже код работает таким образом, что функция on_pick захватывает ваши диски и исправления, а затем возвращает функцию, чтобы указать, какая фигура была нажата.

Если вы хотите придерживаться нескольких обработчиков pick_event, вы можете сделать это, настроив Disk.onpick, как я понял ниже, чтобы определить, было ли событие выбора релевантным для этого диска (каждый диск будет получать каждое событие выбора). Вы заметите, что класс Disk сохраняет свой патч в self.mypatch, чтобы это работало. Если вы хотите сделать это таким образом, отбросьте все изменения, которые я сделал до main, и раскомментируем две строки в Disk.mpl_patch.

import matplotlib as mpl 
import matplotlib.pyplot as plt 
import numpy as np 


class Disk: 


    def __init__(self, center, radius, myid = None, figure=None, axes_object=None): 
     """ 
     @ARGS 
     CENTER : Tuple of floats 
     RADIUS : Float 
     """ 
     self.center = center 
     self.radius = radius 
     self.fig = figure 
     self.ax  = axes_object 
     self.myid = myid 
     self.mypatch = None 


    def onpick(self,event): 
     if event.artist == self.mypatch: 
      print "You picked the disk ", self.myid, " with Center: ", self.center, " and Radius:", self.radius 


    def mpl_patch(self, diskcolor= 'orange'): 
     """ Return a Matplotlib patch of the object 
     """ 
     self.mypatch = mpl.patches.Circle(self.center, self.radius, facecolor = diskcolor, picker=1) 

     #if self.fig != None: 
      #self.fig.canvas.mpl_connect('pick_event', self.onpick) # Activate the object's method 

     return self.mypatch 

def on_pick(disks, patches): 
    def pick_event(event): 
     for i, artist in enumerate(patches): 
      if event.artist == artist: 
       disk = disks[i] 
       print "You picked the disk ", disk.myid, " with Center: ", disk.center, " and Radius:", disk.radius 
    return pick_event 


def main(): 

    fig = plt.figure() 
    ax = fig.add_subplot(111) 
    ax.set_title('click on disks to print out a message') 

    disk_list = [] 
    patches = [] 

    disk_list.append(Disk((0,0), 1.0, 1, fig, ax ) ) 
    patches.append(disk_list[-1].mpl_patch()) 
    ax.add_patch(patches[-1]) 

    disk_list.append(Disk((3,3), 0.5, 2, fig, ax ) ) 
    patches.append(disk_list[-1].mpl_patch()) 
    ax.add_patch(patches[-1]) 

    disk_list.append(Disk((4,9), 2.5, 3, fig, ax ) ) 
    patches.append(disk_list[-1].mpl_patch()) 
    ax.add_patch(patches[-1]) 

    pick_handler = on_pick(disk_list, patches) 

    fig.canvas.mpl_connect('pick_event', pick_handler) # Activate the object's method 

    ax.set_ylim(-2, 10); 
    ax.set_xlim(-2, 10); 

    plt.show() 


if __name__ == "__main__": 
    main() 
+0

Большое вам спасибо! Это сработало отлично! И я должен узнать больше о Python и Matplotlib в этом процессе. Очень признателен. – smilingbuddha

Смежные вопросы