2013-11-19 4 views
2

я использую Matplotlib:Как иметь дело с несколькими объектами прослушивания motion_notify_events на том же рисунке

Допустим, у меня есть объект A, который имеет два атрибута B и C, а также метод, который рисует фигуру. И B, и C имеют методы, делающие некоторые вещи на фигуре на события motion_notify_event.

Я заметил, что оба метода не работают одновременно, и, похоже, конфликт.

Как можно справиться с таким случаем?

Итак, я написал код, который показывает проблему немного лучше, чем приведенное выше объяснение.

import matplotlib.pyplot as plt 
from matplotlib.widgets import MultiCursor 
from matplotlib.patches import Circle 


class Event1(object): 

    def __init__(self,axes): 

     self.fig = axes[0].figure 
     self.axes = axes 

     self.eid = self.fig.canvas.mpl_connect('motion_notify_event',self.onmove) 


    def onmove(self,event): 
     for ax in self.axes: 
      c = Circle((event.xdata,event.ydata),radius=0.05) 
      ax.add_patch(c) 
      ax.draw_artist(c) 

     self.fig.canvas.blit(self.fig.bbox) 



class plotclass(object): 

    def __init__(self): 

     pass 

    def plotme(self): 

     self.fig = plt.figure() 
     self.ax1 = self.fig.add_subplot(211) 
     self.ax2 = self.fig.add_subplot(212) 

     for ax in (self.ax1,self.ax2): 
      ax.set_xlim((0,10)) 
      ax.set_ylim((0,10)) 

#  self.curs = MultiCursor(self.fig.canvas,(self.ax1,self.ax2)) 

     self.ev1 = Event1((self.ax1,self.ax2)) 

     self.fig.show() 



def main(): 

    pc = plotclass() 

    return pc 


if __name__ == '__main__': 
    main() 

Теперь в этом коде есть две вещи слушающий motion_notify_event: класс Event1, который будет рисовать круги в позиции курсора, а класс «plotclass», который создает фигуру и рисует курсоры в позиции курсора ,

Я прокомментировал строку self.curs = ..., и я вижу круги, когда мышь перемещается, но если я раскомментирую ее, я просто вижу курсоры: почему? и как увидеть оба?

+0

Возможно, это связано с тем, что объект 'MultiCursor' использует blitting, и вы его используете. Как ваш класс, так и 'MultiCursor' восстанавливают холст до его начального состояния и blit над ним. Поэтому, какой бы ни был последний, это единственный, который появляется. Быстрое решение состоит в том, чтобы передать «useblit = False» в многокурсник, но это замедлит его. –

ответ

1

Чтобы подробно остановиться на моем комментарии выше, это связано не только с обработкой нескольких событий, это связано с тем, что разные этапы переплетения переписывают друг друга.

Blitting обычно работает, восстанавливая сохраненное, полностью отображаемое состояние, а затем рисует поверх него.

В вашем текущем коде вы бьете, но не восстанавливаете сохраненное состояние, поэтому вы получаете «след» кругов (по-видимому, это то, что вы хотите).

Однако MultiCursor называет fig.canvas.restore_region(...)перед тем рисунок себя (иначе вы бы «след» линий). Поэтому он восстанавливает сохраненную «пустую» фигуру над тем, что вы только что нарисовали.

Если вы хотите использовать несколько проходов бьющих, им нужно будет координировать друг с другом. Существует несколько различных способов справиться с этим, но они преувеличены для большинства случаев использования. Быстрое исправление должно пройти в useblit=False до MultiCursor. Однако это замедлит ваш рендеринг.

Можете ли вы немного рассказать о том, что вы пытаетесь сделать? Вам просто нужен курсор с кругом в позиции мыши? (Если это так, просто подкласс MultiCursor.)

+0

Круги предназначены только для примера. То, что я действительно хочу, - это многокурсник и рисование прямоугольников, поскольку я показал уроку в этом другом сообщении. Http://bpaste.net/show/Fmkw75xZH3JFJbRi2qob/ До сих пор я получал ту же проблему, что и с кругами, то есть я вижу свой многокурсник но не перетаскивают прямоугольники. Конечно, если я использую useblit = False, я вернусь к проблеме, когда рисовать мои прямоугольники для 14 осей слишком медленно, чтобы их можно было использовать. Один из обходных решений, о котором я думал, - это отключить MultiCursor каким-либо образом в событии клика, то есть когда я начну перетаскивать мои прямоугольники. – MCF

+0

@ Хеймдал - Это, наверное, самый легкий. Вы должны подклассифицировать «MultiCursor», чтобы не только разрешить отключить/включить, но и обновить его внутреннее сохраненное состояние холста.Это не слишком сложно, но это будет немного подробней. –

+0

@Heimdall - Вот пример того, как я буду делать это на основе вашего связанного примера. Я также внес несколько изменений в класс 'Zones', который должен помочь в производительности (а также несколько упрощений). https://gist.github.com/joferkington/7566594 –