Python 2.7 使用wxpython从数据流实时绘制轨迹

Python 2.7 使用wxpython从数据流实时绘制轨迹,python-2.7,bitmap,wxpython,real-time,Python 2.7,Bitmap,Wxpython,Real Time,我想用wxpython实时显示随机行走的轨迹。但是,面板在最后仅更新一次,显示整个随机行走,而不是逐步更新并显示时间过程 我的第一个想法是使用wx.ClientDC().DrawPoint(),但结果如上所述,我没有看到绘制的是单个点,但只显示了最终结果 因此,我考虑使用wx.MemoryDC将轨迹绘制到存储在内存中的位图,然后使用wx.ClientDC.DrawBitmap()以设置的时间间隔将缓冲图像复制到屏幕上,以防翻转图像成为瓶颈。结果还是一样,所以我希望你能帮助我 本练习的目的是用帧速

我想用wxpython实时显示随机行走的轨迹。但是,面板在最后仅更新一次,显示整个随机行走,而不是逐步更新并显示时间过程

我的第一个想法是使用wx.ClientDC().DrawPoint(),但结果如上所述,我没有看到绘制的是单个点,但只显示了最终结果

因此,我考虑使用wx.MemoryDC将轨迹绘制到存储在内存中的位图,然后使用wx.ClientDC.DrawBitmap()以设置的时间间隔将缓冲图像复制到屏幕上,以防翻转图像成为瓶颈。结果还是一样,所以我希望你能帮助我

本练习的目的是用帧速率为1000 Hz的眼动跟踪器的位置数据替换随机行走,我希望能够尽可能实时地可视化轨迹(监视器的帧速率为120 Hz)

这是我的代码(大部分来自):

导入wx
随机输入
导入时间
不时地
#-------------------------------------------------------------------
def jmtime():
返回'['+asctime()[11:19]+']'
#-------------------------------------------------------------------
类MyDrawingArea(wx.Window):
定义初始化(自身、父项、id):
sty=wx.NO\U边框
wx.Window.\uuuuu init\uuuuuuuux(self,parent,id,style=sty)
self.parent=parent
self.setbackgroundColor(宽x.白色)
self.SetCursor(wx.CROSS_CURSOR)
#一些初始化,只是为了提醒用户
#存在名为self.BufferBmp的文件。请参见self.OnSize()。
self.BufferBmp=None
wx.EVT_尺寸(自、自尺寸)
wx.EVT_油漆(自油漆、自油漆)
wx.EVT\u左下(self,self.OnClick)
def OnSize(自身、事件):
打印jmtime()+'OnSize in MyDrawingArea'
#获取绘图区域的大小(以像素为单位)。
self.wi,self.he=self.GetSizeTuple()
#创建BufferBmp并设置与绘图区域相同的大小。
self.BufferBmp=wx.EmptyBitmap(self.wi,self.he)
memdc=wx.MemoryDC()
memdc.SelectObject(self.BufferBmp)
#绘图作业
ret=自身的DoSomeDrawing(memdc)
如果不是ret:#错误
self.BufferBmp=None
wx.MessageBox('绘图错误','注释绘图',wx.OK | wx.ICON_感叹号)
def OnPaint(自身、事件):
打印jmtime()+'OnPaint in MyDrawingArea'
dc=wx.PaintDC(自)
dc.BeginDrawing()
如果self.BufferBmp!=无:
打印jmtime()+“…绘图”
dc.DrawBitmap(self.BufferBmp,0,0,True)
其他:
打印jmtime()+“…无需绘制”
dc.EndDrawing()
def OnClick(自我,事件):
pos=event.GetPosition()
dc=wx.ClientDC(自)
直流设置笔(wx.Pen(wx.BLACK,1,wx.SOLID))
dcwi,dche=dc.GetSizeTuple()
x=位置x
y=位置y
time\u start=time.time()
memdc=wx.MemoryDC()
memdc.SelectObject(self.BufferBmp)
memdc.SetPen(wx.Pen(wx.BLACK,1,wx.SOLID))
计数=1
运行时=5
while(time.time()-time\u start)<运行时:
x、 y=随机行走(x,y,dcwi,dche)
memdc.支点(x,y)
如果(time.time()-time_start)>count*runtime*0.1:
打印jmtime()+“MyDrawingArea中的随机漫游”
计数+=1
dc.BeginDrawing()
dc.DrawBitmap(self.BufferBmp,0,0,True)
dc.EndDrawing()
dc.BeginDrawing()
dc.DrawBitmap(self.BufferBmp,0,0,True)
dc.EndDrawing()
#def OnClick结束
def DoSomeDrawing(自身、dc):
尝试:
打印jmtime()+“MyDrawingArea中的DoSomeDrawing”
dc.BeginDrawing()
#~raise OVERLOWERROR#进行测试
#清除一切
直流立根刷(wx刷(wx白色,wx固体))
dc.Clear()
dc.EndDrawing()
返回真值
除:
返回错误
#-------------------------------------------------------------------
类别MyPanel(wx.Panel):
定义初始化(自身、父项、id):
wx.Panel.\uuuuu init\uuuuuuuuuuux(self,parent,id,wx.DefaultPosition,wx.DefaultSize)
self.drawingara=mydrawingara(self,-1)
self.SetAutoLayout(真)
间距=30#像素
lc=wx.LayoutConstraints()
lc.top.SameAs(自我,wx.top,间隙)
lc.left.SameAs(自,wx.left,间隙)
lc.右.相同(自身,宽x.宽度,间隙)
lc.底部相同(自,wx.底部,间隙)
自绘制区域设置约束(lc)
#-------------------------------------------------------------------
#通常的框架。可以调整大小、最大化和最小化。
#框架包含一个面板。
类MyFrame(wx.Frame):
定义初始化(自身、父项、id):
wx.Frame.\uuuuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
self.panel=MyPanel(self,-1)
wx.EVT\u关闭(self,self.OnCloseWindow)
def OnCloseWindow(自身、事件):
打印jmtime()+“MyFrame中的OnCloseWindow”
自我毁灭
#-------------------------------------------------------------------
类MyApp(wx.App):
def OnInit(自身):
frame=MyFrame(无,-1)
frame.Show(真)
self.SetTopWindow(框架)
返回真值
#-------------------------------------------------------------------
def随机行走(x,y,sizex=250,sizey=200):
rn=随机。随机范围(0,2)
x_new=x+(1-rn)-rn
当x_new<0或x_new>sizex时:
rn=随机。随机范围(0,2)
x_new=x+(1-rn)-rn
rn=随机。随机范围(0,2)
y_new=y+(1-rn)-rn
当y_new<0或y_new>sizex时:
rn=随机。随机范围(0,2)
y_new=y+(1-rn)-rn
返回x_new,y_new
#def结束
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-------------------------------------------------------------------
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'