2016-07-25 37 views
1

我是Python的新手,我想爲一個很長時間的系列數據實現一個滾動圖。我從Matplotlib中找到了一個例子,如下所示。Matplotlib:滾動圖

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

當我從鏈接運行的例子中,我發現我每次滾動的情節和釋放滾動條,滾動條返回到最初的時間。想滾動到下一個位置?我需要再次從頭開始滾動。

我想了解它爲什麼會發生,以及如何解決它。

回答

3

下面是該示例的改進版本。 (免責聲明:我半小時前開始挖掘它,以前從未使用過wx/matplotlib滾動條,因此可能會有更好的解決方案。)

我採用的路徑:首先檢查wx scroll events,然後發現畫布是從wxPanel派生的FigureCanvasWxAgg,繼承wxWindow方法。在那裏你可以找到滾動位置處理方法GetScrollPosSetScrollPos

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等