前些天wxpython做得简单代码,目标是:
比如说c:\photos\....下面有很多头像图片,这些图片在上面或下面有一个圆点,呈现图片一段时间,判断圆点在上面还是下面,按1,2进行反应,记录反应时间。
注:是帮朋友进行孤独症儿童注意力分配实验写的,后面因为在处理*.gif图片的时候响应速度不够好,改为用delphi7写了。
程序涉及:
wxpython
事件响应
图片缩放和GIF动画操作
# -*- coding: cp936 -*-
import time
import wx,os
import wx.animate
from operator import or_
from func import *
from threading import *
class M(object):
idx = 0
total = 0
right = 0
wrong = 0
starticker = 0 #开始时间
steps = []
answer = 0
pause = 1000
pre = 'bmp' #0 is bmp,1 is if,2 is text
class FullScreenPanel(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self,parent,name="FullScreenPanel",style= wx.DEFAULT_FRAME_STYLE | wx.WANTS_CHARS )
self.SetBackgroundColour('black')
self.TrialBtn = wx.Button(self,label="练习")
self.TrialBtn.Bind(wx.EVT_BUTTON,self.BeginTrial)
self.TestBtn = wx.Button(self,label="测试")
self.TestBtn.Bind(wx.EVT_BUTTON,self.BeginTest)
sizer = wx.BoxSizer(orient=wx.VERTICAL)
sizer.AddStretchSpacer()
sizer.Add(self.TrialBtn,0, wx.ALIGN_CENTER )
sizer.Add(self.TestBtn,0, wx.ALIGN_CENTER )
sizer.AddStretchSpacer()
self.SetSizer(sizer)
self.Layout()
def hideImg(self):
try:
self.curImg.Show(False)
except:
pass
def hideGif(self):
try:
self.curGif.Stop()
self.curGif.Close()
self.curGif.Show(False)
except:
print "hide gif error"
pass
def hideText(self):
try:
self.curText.Show(False)
except:
pass
def KeyDownResponse(self,evt):
code = evt.GetKeyCode()
if code in (49,50):
self.stopTimer()
self.Bind(wx.EVT_KEY_DOWN,self.KeyDownNull)
if code == 49:
code = 1
else:
code = 2
if code == M.answer:
slapedTime = time.time() - M.starticker
self.show(response['right'])
M.right = M.right + 1
M.total = M.total + 1
rate = M.right/float(M.total)
else:
slapedTime = time.time() - M.starticker
self.show(response['wrong'])
M.wrong = M.wrong + 1
M.total = M.total + 1
rate = M.right/float(M.total)
text = "正确率:%.3f 耗时:%.3f" % (rate,slapedTime)
if self.practice:
self.addText(text)
self.fp.write(text+"\n")
self.timer = wx.CallLater(M.pause,self.next)
else:
pass
def addText(self,text):
mm=wx.DisplaySize()
x0 = 100
y0 = 600
self.curText = wx.StaticText(self,-1,text,(x0,y0),(160,0),wx.ALIGN_CENTER)
font=wx.Font(18,wx.DECORATIVE,wx.NORMAL,wx.NORMAL)
self.curText.SetFont(font)
self.curText.SetForegroundColour("white")
self.curText.SetBackgroundColour("black")
self.curText.Show(True)
def KeyDownNull(self,evt):
pass
def showText(self,text):
mm=wx.DisplaySize()
x0 = (mm[0] - 60) / 2
y0 = (mm[1] - 60) / 2
self.curText = wx.StaticText(self,-1,text,(x0,y0),(160,0),wx.ALIGN_CENTER)
font=wx.Font(28,wx.DECORATIVE,wx.NORMAL,wx.NORMAL)
self.curText.SetFont(font)
self.curText.SetForegroundColour("white")
self.curText.SetBackgroundColour("black")
self.curText.Show(True)
def showBmp(self,fpath):
try:
self.curImg.Show(False)
except:
pass
mm=wx.DisplaySize()
img = wx.Image(fpath, wx.BITMAP_TYPE_BMP)
x0 = (mm[0] - img.GetWidth()) / 2
y0 = (mm[1] - img.GetHeight()) / 2
wxBitmap = img.ConvertToBitmap()
# self.curImg.SetBitmap(wxBitmap)
self.curImg = wx.StaticBitmap(self, -1, img.ConvertToBitmap(), (x0,y0), (img.GetWidth(), img.GetHeight()))
self.curImg.Show(True)
print "end.."+fpath
def showGif(self,fpath):
mm=wx.DisplaySize()
img = wx.Image(fpath, wx.BITMAP_TYPE_GIF)
x0 = (mm[0] - img.GetWidth()) / 2
y0 = (mm[1] - img.GetHeight()) / 2
self.curGif = wx.animate.GIFAnimationCtrl(self, -1, fpath, (x0,y0), (img.GetWidth(), img.GetHeight()))
self.curGif.GetPlayer().UseBackgroundColour(True)
self.curGif.Play()
def show(self,fpath):
type = getType(fpath)
self.hideText()
self.hideGif()
if not type == M.pre:
if type == "gif":
self.hideText()
self.hideImg()
self.hideGif()
elif type == "bmp":
self.hideGif()
self.hideText()
else:
self.hideImg()
self.hideGif()
M.pre = type
print 'show '+fpath
if type == "bmp":
self.hideText()
self.showBmp(fpath)
elif type == "gif":
self.hideText()
self.showGif(fpath)
elif type == "":
self.showText(fpath)
def stopTimer(self):
self.timer.Stop()
def timeout(self):
self.stopTimer()
self.Bind(wx.EVT_KEY_DOWN,self.KeyDownNull)
self.show(response['timeout'])
M.total += 1
rate = M.right / float(M.total)
slapedTime = time.time() - M.starticker
text = "正确率:%.3f %.3f" % (rate,slapedTime)
if self.practice:
self.addText(text)
self.fp.write(text+"\n")
self.timer = wx.CallLater(M.pause,self.next)
def next(self):
idx = M.idx
if idx > len(M.steps)-1:
self.stopTimer()
print "over"
return ""
print 'current idx %s' %idx
opType = M.steps[idx][0]
fpath = M.steps[idx][1]
type = getType(fpath)
sepTime = M.steps[idx][2]
M.idx = idx+1
self.show(fpath)
if opType == 0: #退出
self.Bind(wx.EVT_KEY_DOWN,self.KeyDownOver)
if opType == 1: #等待space
self.Bind(wx.EVT_KEY_DOWN,self.KeyDownTrigger)
elif opType in (2,3): #空操作
self.Bind(wx.EVT_KEY_DOWN,self.KeyDownNull)
self.timer = wx.CallLater(sepTime, self.next)
elif opType == 4: #等待反映,1500ms 后
self.Bind(wx.EVT_KEY_DOWN,self.KeyDownResponse) #多做一次也无所谓,让逻辑
M.starticker = time.time()
self.timer = wx.CallLater(sepTime, self.timeout)
elif opType == 9:
M.answer = M.steps[idx][3]
self.Bind(wx.EVT_KEY_DOWN,self.KeyDownResponse)
self.timer = wx.CallLater(sepTime, self.next)
def KeyDownOver(self,evt):
self.stopTimer()
self.hideGif()
self.hideText()
self.hideImg()
self.TrialBtn.Show()
self.TestBtn.Show()
try:
self.fp.close()
except:
pass
M.steps = []
M.idx = 0
M.total = 0
M.right = 0
M.wrong = 0
M.starticker = 0 #开始时间
M.steps = []
M.answer = 0
def KeyDownTrigger(self,evt):
if evt.GetKeyCode() == 32:
self.next()
def getSavePath(self):
sp = time.strftime("%Y-%m-%d-%H-%M-%S",time.localtime())+".txt"
return os.path.join(os.getcwd(),sp)
def BeginTest(self,evt):
fpath = self.getSavePath()
self.fp = open(fpath, 'w')
self.practice = False
self.TrialBtn.Hide()
self.TestBtn.Hide()
M.steps = getSteps(testConf)
print M.steps
self.next()
self.FullScreen(evt)
def BeginTrial(self,evt):
fpath = self.getSavePath()
self.fp = open(fpath, 'w')
self.practice = True
self.TrialBtn.Hide()
self.TestBtn.Hide()
M.steps = getSteps(trialConf)
self.next()
self.FullScreen(evt)
def GetFlags(self):
res = []
val = "FULLSCREEN_ALL"
res.append(getattr(wx,val))
return reduce(or_,res,0)
def FullScreen(self,evt):
top = self.GetTopLevelParent()
top.OnFullScreen(evt)
class MainFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, wx.ID_ANY, 'Test FullScreen', size=(600, 400))
self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
self.client = FullScreenPanel(self)
mbar = wx.MenuBar()
the_menu = wx.Menu()
fullscreenMI = the_menu.Append(wx.ID_ANY,"Full Screen\tF12","Toggles Full Screen Mode")
mbar.Append(the_menu,"File")
self.SetMenuBar(mbar)
self.Bind(wx.EVT_MENU,self.OnFullScreen,id=fullscreenMI.GetId())
def OnCloseWindow(self, event):
self.Destroy()
def OnFullScreen(self,event):
flags = self.client.GetFlags()
self.ShowFullScreen(not self.IsFullScreen(),flags)
class MainApp(wx.App):
def OnInit(self):
self.main = MainFrame(None)
self.main.Show()
self.SetTopWindow(self.main)
return True
def main():
application = MainApp(redirect=False)
application.MainLoop()
if __name__=='__main__':
main()
# -*- coding: cp936 -*-
import os
import random
import wx
def opj(path):
st = apply(os.path.join, tuple(path.split('/')))
if path.startswith('/'):
st = '/' + st
return st
imgTypeDict = {
'bmp':wx.BITMAP_TYPE_BMP,
'gif':wx.BITMAP_TYPE_GIF,
'png':wx.BITMAP_TYPE_PNG,
'jpg':wx.BITMAP_TYPE_JPEG
}
#获取后缀
def getType(o):
if o.rfind(".") > -1:
idx=o.rindex(".")+1
return o[idx:].lower()
else:
return ""
p1 = opj('photos/right.bmp')
p2 = opj('photos/wrong.bmp')
p3 = opj('photos/no response.bmp')
response = {
'right':p1,
'wrong':p2,
'timeout':p3
}
sep = (2,'+',1000)
sep0 = (2,'',1000)
trialConf = (
(1,'photos/welcome.bmp'),
(1,'photos/instruction.bmp'),
(2,'+',1), #1000ms 文本
(3,'photos/practice/face1', 400,200,1500),
#探测的文件目录时间(面空时间,探测点时间,等待回答时间)
(0,'photos/goodbye.bmp',5000)
)
testConf = (
(1,'photos/welcome.bmp'),
(1,'photos/instruction.bmp'),
(2,'+',1000), #1000ms 文本
(3,'photos/donghua', 400,50,1500),
#探测的文件目录时间(面空时间,探测点时间,等待回答时间)
(0,'photos/goodbye.bmp',5000)
)
def getSteps(conf):
steps=[]
for x in conf:
type = x[0]
img = x[1]
if type == 0: #end
item = (0,opj(x[1]),-1)
steps.append(item)
if type == 1: #单个图片
item = (1,opj(x[1]),-1) #-1 means infinate
steps.append(item)
elif type == 2: #
item = (2,x[1],x[2]) #内容,时间
steps.append(item)
elif type == 3:
dir1 = x[1]
t1 = x[2]
t2 = x[3]
t3 = x[4]
face=[]
probe=[]
for root, dirs, files in os.walk(dir1, topdown=False):
for name in files:
if name.endswith(".gif") or name.endswith(".bmp"):
face.append(opj(os.path.join(root, name)))
face.sort()
print face
count = len(face)
i=0
while(i<count):
curImg = face[i]
i += 1
nextImg = face[i]
if nextImg.find("_2") > 0: #存在2,就是下面有点
answer = 2
else:
answer = 1
i += 1
curItem = (curImg,nextImg,answer)
probe.append(curItem)
# print face
random.shuffle(probe)
i=0
count = len(probe)
# print probe
while(i<count):
curItem = probe[i]
item = (3,curItem[0],t1)
steps.append(item)
item = (9,curItem[1],t2,curItem[2])
#马上要激活keyboard反应,并置相应的时间处理函数
#(类型4需要响应,图片路径,呈现时间,正确答案,超时时间,
steps.append(item)
item = (4,curItem[0],t3)
steps.append(item)
steps.append(sep0)
steps.append(sep)
i += 1
return steps