Je veux utiliser wxpython pour montrer la trajectoire d'une marche aléatoire en temps réel. Cependant, le panneau n'est mis à jour qu'une seule fois à la fin, montrant l'ensemble de la marche aléatoire au lieu de la mettre à jour pas à pas et de montrer l'évolution dans le temps. La première idée consistait à utiliser wx.ClientDC(). DrawPoint() mais le résultat était comme décrit ci-dessus où je ne voyais pas de points uniques dessinés mais seul le résultat final était affiché. Donc à la place, j'ai pensé à utiliser wx.MemoryDC pour dessiner la trajectoire vers un bitmap stocké en mémoire, puis utiliser wx.ClientDC.DrawBitmap() pour copier l'image tamponnée à l'écran à des intervalles de temps définis au cas où l'image serait retournée était le goulot d'étranglement. Le résultat est toujours le même et j'espère que vous m'aiderez. Le but de cet exercice est de remplacer la marche aléatoire par des données de position provenant d'un eye tracker avec une fréquence d'images de 1000 Hz et j'aimerais pouvoir visualiser la trajectoire le plus près possible en temps réel (La fréquence d'image du moniteur est de 120 Hz).Dessiner une trajectoire à partir d'un flux de données en temps réel en utilisant wxpython
Ceci est mon code (la majeure partie provient de 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-------------------------------------------------------------------