You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌套循环键盘事件处理求助:停止信号反应任务编程

解决Stop Signal Response Task中的Pygame键盘响应卡顿与记录问题

嘿,我看了你这个停止信号任务的代码问题,核心是Pygame的事件处理逻辑没捋顺,还有几个小的时间计算笔误,咱们一步步来搞定它:

先修正几个明显的逻辑笔误

  • 你代码里的while time.time() < SSD应该是while time.time() < StopSignalTime,因为SSD是延迟时长,StopSignalTime = starttime + SSD才是蜂鸣触发的具体时间点
  • 调整SSD的代码里SSD = SSD = 0.05是笔误,按照停止信号任务的规则,应该是SSD = SSD - 0.05(被试没抑制住反应时,缩短下一次的SSD)

Pygame键盘事件的正确打开方式

之所以会出现“无法记录响应”或“程序卡顿”,是因为你没正确处理Pygame的事件队列,而且用了忙等的循环(一直占用CPU)。正确的做法是:

  1. 初始化Pygame时必须创建窗口(哪怕后台运行,Pygame需要窗口才能捕获输入)
  2. 用事件队列处理按键,而不是直接检测按键状态(避免重复触发)
  3. 用帧率控制减少CPU占用,防止卡顿

完整的试次循环代码示例

先放初始化代码:

import pygame
import time

# 初始化Pygame核心模块
pygame.init()
# 创建窗口(可以设置为全屏:pygame.display.set_mode((0,0), pygame.FULLSCREEN))
screen = pygame.display.set_mode((800, 600))
# 禁止按键重复触发(避免按住键时多次记录)
pygame.key.set_repeat(0)
# 用于控制帧率的时钟对象
clock = pygame.time.Clock()

# 假设你已经定义了这些变量:
beeplist = [1, 0, 1, 0]  # 示例蜂鸣列表
SSD = 0.3  # 初始停止信号延迟
trial_ST = []  # 存储试次开始时间
response = []  # 存储响应(按键+反应时间)
SSDlist = []  # 存储每次试次的SSD

然后是单个试次的核心处理逻辑:

# 遍历试次(这里用i作为示例索引)
for i in range(len(beeplist)):
    starttime = time.time()
    trial_ST.append(starttime)
    end_time = starttime + 1.250  # 试次总时长1.25秒
    StopSignalTime = starttime + SSD  # 蜂鸣触发的时间点
    presses = None  # 存储首次按键
    rt = None  # 存储反应时间
    ss_played = False  # 标记蜂鸣是否已播放

    # 试次主循环:持续到试次结束时间
    while time.time() < end_time:
        # 处理所有Pygame事件(必须做,否则程序会卡顿)
        for event in pygame.event.get():
            # 处理窗口关闭事件,防止程序卡死
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()
            # 仅在未记录过按键时,处理按键按下事件
            if event.type == pygame.KEYDOWN and presses is None:
                # 只记录目标按键z或/
                if event.key == pygame.K_z:
                    presses = 'z'
                    rt = time.time() - starttime
                elif event.key == pygame.K_SLASH:
                    presses = '/'
                    rt = time.time() - starttime
        
        # 检查是否需要播放蜂鸣(仅播放一次)
        if beeplist[i] == 1 and not ss_played and time.time() >= StopSignalTime:
            # 这里假设tone是你已经初始化好的pygame.mixer.Sound对象
            tone.play()
            ss_played = True
        
        # 控制帧率为60帧/秒,减少CPU占用,避免卡顿
        clock.tick(60)
    
    # 将响应存入列表(按键+反应时间,无按键则存None)
    response.append((presses, rt))
    # 记录本次试次的SSD
    SSDlist.append(SSD)

    # 根据表现调整SSD
    if beeplist[i] == 1:
        if presses is None:
            # 成功抑制反应,增加SSD
            SSD += 0.05
        else:
            # 未抑制住反应,减少SSD(修正你的笔误)
            SSD -= 0.05
        # 限制SSD的范围,避免不合理值
        SSD = max(0.0, min(SSD, 1.25))
    
    print("end of block iteration")
    # 你的blockiteration和restblock()逻辑
    # blockiteration += 1
    # restblock()

关键细节解释

  • 事件队列处理:用pygame.event.get()遍历所有事件,只在KEYDOWN且presses为None时记录按键,确保只捕获首次响应,不会重复记录。
  • 蜂鸣播放控制:用ss_played标记,避免在循环中多次触发蜂鸣播放(因为循环会每秒运行60次,不标记的话会重复播放)。
  • 帧率控制:clock.tick(60)让循环每秒最多运行60次,既保证按键检测的灵敏度,又不会让CPU跑满导致卡顿。
  • 反应时间计算:在按键按下的瞬间计算time.time() - starttime,确保反应时间的准确性。
  • SSD范围限制:用max(0.0, min(SSD, 1.25))保证SSD不会小于0(蜂鸣提前播放)或大于试次时长(蜂鸣不会触发)。

内容的提问来源于stack exchange,提问作者Richard Summers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:59:15