2016-07-25 2 views
1

Я новичок в Python, и я хочу реализовать прокрутку для очень длинных временных рядов. Я нашел пример из Matplotlib следующим образом.Matplotlib: scrolling plot

http://scipy-cookbook.readthedocs.io/items/Matplotlib_ScrollingPlot.html

Когда я запускаю пример из ссылки, я обнаружил, каждый раз, когда я прокрутить сюжет и освободить полосы прокрутки, скроллбар возвращается к началу. Хотите перейти к следующей позиции? Мне нужно начать прокручивать с самого начала.

Я хочу понять, почему это происходит и как его исправить.

ответ

3

Вот улучшенная версия примера. (Отказ от ответственности: я начал копаться в нем полчаса назад, никогда раньше не использовал полосы прокрутки wx/matplotlib, поэтому могло бы быть гораздо лучшее решение.)

Путь, который я взял: сначала я проверил wx scroll events, а затем выяснил, что холст FigureCanvasWxAgg, полученный из wxPanel, наследующий wxWindow методов. Там вы можете найти методы обработки прокрутки GetScrollPos и SetScrollPos.

from numpy import arange, sin, pi, float, size 

import matplotlib 
matplotlib.use('WXAgg') 
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg 
from matplotlib.figure import Figure 

import wx 

class MyFrame(wx.Frame): 
    def __init__(self, parent, id): 
     wx.Frame.__init__(self,parent, id, 'scrollable plot', 
       style=wx.DEFAULT_FRAME_STYLE^wx.RESIZE_BORDER, 
       size=(800, 400)) 
     self.panel = wx.Panel(self, -1) 

     self.fig = Figure((5, 4), 75) 
     self.canvas = FigureCanvasWxAgg(self.panel, -1, self.fig) 
     self.scroll_range = 400 
     self.canvas.SetScrollbar(wx.HORIZONTAL, 0, 5, 
           self.scroll_range) 

     sizer = wx.BoxSizer(wx.VERTICAL) 
     sizer.Add(self.canvas, -1, wx.EXPAND) 

     self.panel.SetSizer(sizer) 
     self.panel.Fit() 

     self.init_data() 
     self.init_plot() 

     self.canvas.Bind(wx.EVT_SCROLLWIN, self.OnScrollEvt) 

    def init_data(self): 

     # Generate some data to plot: 
     self.dt = 0.01 
     self.t = arange(0,5,self.dt) 
     self.x = sin(2*pi*self.t) 

     # Extents of data sequence: 
     self.i_min = 0 
     self.i_max = len(self.t) 

     # Size of plot window: 
     self.i_window = 100 

     # Indices of data interval to be plotted: 
     self.i_start = 0 
     self.i_end = self.i_start + self.i_window 

    def init_plot(self): 
     self.axes = self.fig.add_subplot(111) 
     self.plot_data = \ 
        self.axes.plot(self.t[self.i_start:self.i_end], 
           self.x[self.i_start:self.i_end])[0] 

    def draw_plot(self): 

     # Update data in plot: 
     self.plot_data.set_xdata(self.t[self.i_start:self.i_end]) 
     self.plot_data.set_ydata(self.x[self.i_start:self.i_end]) 

     # Adjust plot limits: 
     self.axes.set_xlim((min(self.t[self.i_start:self.i_end]), 
          max(self.t[self.i_start:self.i_end]))) 
     self.axes.set_ylim((min(self.x[self.i_start:self.i_end]), 
          max(self.x[self.i_start:self.i_end]))) 

     # Redraw: 
     self.canvas.draw() 

    def update_scrollpos(self, new_pos): 
     self.i_start = self.i_min + new_pos 
     self.i_end = self.i_min + self.i_window + new_pos 
     self.canvas.SetScrollPos(wx.HORIZONTAL, new_pos) 
     self.draw_plot() 

    def OnScrollEvt(self, event): 
     evtype = event.GetEventType() 

     if evtype == wx.EVT_SCROLLWIN_THUMBTRACK.typeId: 
      pos = event.GetPosition() 
      self.update_scrollpos(pos) 
     elif evtype == wx.EVT_SCROLLWIN_LINEDOWN.typeId: 
      pos = self.canvas.GetScrollPos(wx.HORIZONTAL) 
      self.update_scrollpos(pos + 1) 
     elif evtype == wx.EVT_SCROLLWIN_LINEUP.typeId: 
      pos = self.canvas.GetScrollPos(wx.HORIZONTAL) 
      self.update_scrollpos(pos - 1) 
     elif evtype == wx.EVT_SCROLLWIN_PAGEUP.typeId: 
      pos = self.canvas.GetScrollPos(wx.HORIZONTAL) 
      self.update_scrollpos(pos - 10) 
     elif evtype == wx.EVT_SCROLLWIN_PAGEDOWN.typeId: 
      pos = self.canvas.GetScrollPos(wx.HORIZONTAL) 
      self.update_scrollpos(pos + 10) 
     else: 
      print "unhandled scroll event, type id:", evtype 

class MyApp(wx.App): 
    def OnInit(self): 
     self.frame = MyFrame(parent=None,id=-1) 
     self.frame.Show() 
     self.SetTopWindow(self.frame) 
     return True 

if __name__ == '__main__': 
    app = MyApp() 
    app.MainLoop() 

Вы можете настроить, например. приращения для PAGEUP/PAGEDOWN, если вы чувствуете, что это слишком медленно.

Кроме того, если вы хотите, то события могут быть обработаны отдельно настройки конкретных обработчиков событий вместо их сбора EVT_SCROLLWIN, то вместо того, если/elifs будет OnScrollPageUpEvt и т.д.