在While循环中单击鼠标(PsychoPy)

时间:2014-04-16 14:43:42

标签: python while-loop mouseevent psychopy

我正在使用PsychoPy,我想在点击鼠标时打印鼠标的位置。

位置的实际打印需要放在while循环中。使用下面的代码,当我点击时,我得到多个输出线,打印相同的位置。我希望每次点击只打印一次。

这是我正在使用的代码:

#!/usr/bin/env python2
from psychopy import visual, core, event
from pyglet.gl import *

width = 600
height = 600
myWin = visual.Window([width,height], color='white',units='pix',monitor='testMonitor')

#This will set the windows units (pixels) to GL units
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, width, 0, height, -1, 1)

glMatrixMode(GL_MODELVIEW)
glLoadIdentity()

glEnable(GL_BLEND)
glBlendFunc(GL_ZERO, GL_SRC_COLOR)

myMouse = event.Mouse()  #  will use myWin by default


while True:
    #Triangle left
    glColor3f(1.0, 0.0, 0.0)
    glBegin(GL_TRIANGLES)
    glVertex3f(150, 550, 1)
    glVertex3f(50, 350, 1)
    glVertex3f(250, 350, -1)
    glEnd()

    if myMouse.getPressed()[0]:
        myMouse.clickReset()
        print myMouse.getPos()

    myWin.flip()

core.quit()

我有什么不对劲吗?应该是'帧速率' while循环的更改?

3 个答案:

答案 0 :(得分:3)

我没有使用该模块,但似乎鼠标事件也被抛出鼠标加注

您需要

  • 将鼠标状态存储下次

  • 每次迭代,测试按钮0的鼠标状态是否上升→下降

myMouse.getPressed返回鼠标状态。

类似于:

oldMouseIsDown = False

while True:
    ...

    mouseIsDown = myMouse.getPressed()[0]
    myMouse.clickReset()

    if mouseIsDown and not oldMouseIsDown:
        print myMouse.getPos()

    oldMouseIsDown = mouseIsDown

答案 1 :(得分:3)

Veedrac的回答是正确的。每次重绘窗口时,您的代码都使用典型的PsychoPy模式来检查事件。这通常至少发生在60赫兹。因此,除非您设法按下鼠标按钮的时间少于16.7毫秒(或更短的速度以获得更快的屏幕),您将按下时多次检测到它,因为每次检查连续的窗口重绘时,鼠标按钮都会保持关闭状态。即使只推了一次,推动的持续时间也不是瞬间的。

正如Veedrac建议的那样,因此您需要在变量中保持鼠标按钮的先前状态,以便您可以选择仅打印一次位置。鼠标悬停事件与此无关:您只是在测试按钮当前是否被按下。

答案 2 :(得分:2)

我有一个非常类似的问题并以与接受的答案略有不同的方式修复它。这个的优点是你可以设置你想要多长时间去除敏感'点击后鼠标(即防止长时间点击多次触发if循环)。根据您的鼠标或用户的点击释放速度,您可以更改minFramesAfterClick

minFramesAfterClick = 10 # to prevent re-entering the if loop too early
myMouse.clickReset()
timeAfterClick = 0
while True:
    timeAfterClick += 1
    if myMouse.getPressed()[0] and timeAfterClick >= minFramesAfterClick:
         print myMouse.getPos()
         myMouse.clickReset()
         timeAfterClick = 0
    myWin.flip()

顺便说一下,OP无法让Veedrac的回答工作的原因是因为行oldMouseIsDown = mouseIsDown应该放在if循环中而不是它之后(没有足够的声誉评论那里)。