2017-07-06 9 views
0

wxpythonを使用して、ランダムウォークの軌道をリアルタイムで表示したいと考えています。しかし、パネルは、ステップごとに更新して時間経過を示す代わりに、ランダムウォーク全体を示す最後に1回だけ更新されます。wxpythonを使用してデータストリームからリアルタイムに軌跡を描きます。

私の最初のアイデアはwx.ClientDC()を使用することでした。DrawPoint()しかし、結果は上記のようになりました。ここでは単一点が描画されていないが、最終結果のみが表示されていました。

代わりに、wx.MemoryDCを使用してメモリに保存されたビットマップに軌跡を描画し、イメージを反転させる場合にwx.ClientDC.DrawBitmap()を使用してバッファリングされたイメージを設定された時間間隔で画面にコピーしましたボトルネックだった。結果はまだ同じですので、私はあなたが助けてくれることを望んでいます。

この練習の目的は、フレームレートが1000 Hzのアイトラッカーからの位置データでランダムウォークを置き換えることです。軌道をできるだけリアルタイムで視覚化できるようにしたいと思います(モニタのフレームレートは120Hzです)。

これは私のコード(そのほとんどがhereから来ている)である:

import wx 
import random 
import time 
from time import asctime 

#------------------------------------------------------------------- 

def jmtime(): 
    return '[' + asctime()[11:19] + '] ' 

#------------------------------------------------------------------- 
class MyDrawingArea(wx.Window): 

    def __init__(self, parent, id): 
     sty = wx.NO_BORDER 
     wx.Window.__init__(self, parent, id, style=sty) 
     self.parent = parent 
     self.SetBackgroundColour(wx.WHITE) 
     self.SetCursor(wx.CROSS_CURSOR) 

     # Some initalisation, just to reminds the user that a variable 
     # called self.BufferBmp exists. See self.OnSize(). 
     self.BufferBmp = None 

     wx.EVT_SIZE(self, self.OnSize) 
     wx.EVT_PAINT(self, self.OnPaint) 
     wx.EVT_LEFT_DOWN(self,self.OnClick) 

    def OnSize(self, event): 
     print jmtime() + 'OnSize in MyDrawingArea' 
     # Get the size of the drawing area in pixels. 
     self.wi, self.he = self.GetSizeTuple() 
     # Create BufferBmp and set the same size as the drawing area. 
     self.BufferBmp = wx.EmptyBitmap(self.wi, self.he) 
     memdc = wx.MemoryDC() 
     memdc.SelectObject(self.BufferBmp) 
     # Drawing job 
     ret = self.DoSomeDrawing(memdc) 
     if not ret: #error 
      self.BufferBmp = None 
      wx.MessageBox('Error in drawing', 'CommentedDrawing', wx.OK | wx.ICON_EXCLAMATION) 


    def OnPaint(self, event): 
     print jmtime() + 'OnPaint in MyDrawingArea' 
     dc = wx.PaintDC(self) 
     dc.BeginDrawing() 
     if self.BufferBmp != None: 
      print jmtime() + '...drawing' 
      dc.DrawBitmap(self.BufferBmp, 0, 0, True) 
     else: 
      print jmtime() + '...nothing to draw' 
     dc.EndDrawing() 



    def OnClick(self,event): 
     pos = event.GetPosition() 
     dc = wx.ClientDC(self) 
     dc.SetPen(wx.Pen(wx.BLACK,1,wx.SOLID)) 

     dcwi, dche = dc.GetSizeTuple() 
     x = pos.x 
     y = pos.y 
     time_start = time.time() 

     memdc = wx.MemoryDC() 
     memdc.SelectObject(self.BufferBmp) 
     memdc.SetPen(wx.Pen(wx.BLACK,1,wx.SOLID)) 
     count = 1 
     runtime = 5 
     while (time.time() - time_start) < runtime: 
      x,y = random_walk(x,y,dcwi,dche) 
      memdc.DrawPoint(x,y) 
      if (time.time() - time_start) > count * runtime * 0.1: 
       print jmtime() + 'Random walk in MyDrawingArea' 
       count += 1 
       dc.BeginDrawing() 
       dc.DrawBitmap(self.BufferBmp, 0, 0, True) 
       dc.EndDrawing() 
     dc.BeginDrawing()   
     dc.DrawBitmap(self.BufferBmp, 0, 0, True) 
     dc.EndDrawing() 

    # End of def OnClick 

    def DoSomeDrawing(self, dc): 
     try: 
      print jmtime() + 'DoSomeDrawing in MyDrawingArea' 

      dc.BeginDrawing() 

      #~ raise OverflowError #for test 

      # Clear everything 
      dc.SetBrush(wx.Brush(wx.WHITE, wx.SOLID)) 
      dc.Clear() 

      dc.EndDrawing() 
      return True 

     except: 
      return False 

#------------------------------------------------------------------- 

class MyPanel(wx.Panel): 

    def __init__(self, parent, id): 
     wx.Panel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize) 

     self.drawingarea = MyDrawingArea(self, -1) 

     self.SetAutoLayout(True) 

     gap = 30 #in pixels 
     lc = wx.LayoutConstraints() 
     lc.top.SameAs(self, wx.Top, gap) 
     lc.left.SameAs(self, wx.Left, gap) 
     lc.right.SameAs(self, wx.Width, gap) 
     lc.bottom.SameAs(self, wx.Bottom, gap) 
     self.drawingarea.SetConstraints(lc) 

#------------------------------------------------------------------- 

# Usual frame. Can be resized, maximized and minimized. 
# The frame contains one panel. 
class MyFrame(wx.Frame): 

    def __init__(self, parent, id): 
     wx.Frame.__init__(self, parent, id, 'CommentedDrawing', wx.Point(0, 0), wx.Size(500, 400)) 
     self.panel = MyPanel(self, -1) 

     wx.EVT_CLOSE(self, self.OnCloseWindow) 

    def OnCloseWindow(self, event): 
     print jmtime() + 'OnCloseWindow in MyFrame' 
     self.Destroy() 

#------------------------------------------------------------------- 

class MyApp(wx.App): 

    def OnInit(self): 
     frame = MyFrame(None, -1) 
     frame.Show(True) 
     self.SetTopWindow(frame) 
     return True 

#------------------------------------------------------------------- 

def random_walk(x,y,sizex = 250, sizey = 200): 

    rn = random.randrange(0,2) 
    x_new = x + (1-rn) - rn 
    while x_new < 0 or x_new > sizex: 
     rn = random.randrange(0,2) 
     x_new = x + (1-rn) - rn 

    rn = random.randrange(0,2) 
    y_new = y + (1-rn) - rn 
    while y_new < 0 or y_new > sizex: 
     rn = random.randrange(0,2) 
     y_new = y + (1-rn) - rn 

    return x_new, y_new 

# end of def random_walk 

#------------------------------------------------------------------- 

def main(): 
    print 'main is running...' 
    app = MyApp(0) 
    app.MainLoop() 

#------------------------------------------------------------------- 

if __name__ == "__main__" : 
    main() 

#eof------------------------------------------------------------------- 

答えて

0

これは私が思いついたのソリューションです。 dc.DrawBitmap()を使用してバッファリングされたイメージを画面にコピーするのではなく、Update()およびRefresh()を使用してペイントイベントをトリガーしました。しかし、私がまだ理解していないのは、同じ目的を達成するためにDrawBitmap()を使用できない理由です。

唯一の違いは、OnPaint()がPaintDC()を使用し、OnClick()でClientDC()を使用する点です。

とにかく、これは、クリック時のために私の現在のコード()である:

def OnClick(self,event): 
    pos = event.GetPosition() 
    x = pos.x 
    y = pos.y 
    time_start = time.time() 

    memdc = wx.MemoryDC() 
    memdc.SelectObject(self.BufferBmp) 
    dcwi, dche = memdc.GetSizeTuple() 
    memdc.SetPen(wx.Pen(wx.BLACK,1,wx.SOLID)) 
    runtime = 10 
    while (time.time() - time_start) < runtime: 
     x,y = random_walk(x,y,dcwi,dche) 
     memdc.SelectObject(self.BufferBmp) 
     memdc.DrawPoint(x,y) 
     memdc.SelectObject(wx.NullBitmap) 
     self.Update() 
     self.Refresh() 
    print jmtime() + 'Random walk in MyDrawingArea done' 
関連する問題