【问题标题】:pygame window not responding when clicked单击时pygame窗口没有响应
【发布时间】:2015-01-29 02:26:38
【问题描述】:

我正在使用 pygame 在我正在处理的项目中进行界面显示和控制器输入。目前一切运行良好,所以这不是主要问题,但如果在实际使用过程中意外发生,可能会出现一些问题,所以我想尽可能地修复它。

当我运行我的代码时,pygame 窗口会按预期出现、显示和更新。但是,如果我单击它或它以其他方式获得焦点,窗口将冻结并变为(无响应)。代码本身继续运行,包括负责更新显示的线程,直到我关闭窗口,所以 Python 本身仍然运行良好,但窗口停止工作。

我的更新循环代码在这里,非常丑陋:

    while(1):
        print "thread is fine"
        pygame.event.pump()

        if LOV_Flag == 1:
            videoColor = (255, 0, 0)
        else:
            videoColor = (0, 255, 0)

        # Refresh the screen and redraw components

        screen.fill((255, 255, 255))
        pulseLabel = pulseFont.render("Pulse: ", 1, (0, 0, 0))
        videoLabel = videoFont.render("Video: ", 1, (0, 0, 0))
        motorsLabel = labelFont.render("Motors", 1, (0, 0, 0))
        motorLabel = captionFont.render("L         R", 1, (0, 0, 0))
        armLabel = captionFont.render("Arm", 1, (0, 0, 0))
        gripperLabel = captionFont.render("Gripper", 1, (0, 0, 0))
        screen.blit(motorsLabel, (55, 50))
        screen.blit(motorLabel, (60, 75))
        screen.blit(pulseLabel, (300, 19))
        screen.blit(videoLabel, (300, 45))
        screen.blit(armLabel, (250, 75))
        screen.blit(gripperLabel, (235, 255))
        leftBar = (50, 200 - drive.getSpeed()[0], 25, drive.getSpeed()[0])
        rightBar = (100, 200 - drive.getSpeed()[1], 25, drive.getSpeed()[1])
        armBar = (250, 200 - (100 * arm.report()), 25, (100 * arm.report()))
        upperArmBar = (250, 200 - (100 * arm.reportUp()), 25, 2) # 100 is the value on the bar
        lowerArmBar = (250, 200 - (100 * arm.reportDown()), 25, 2) # 135 (65) is the value on the bar
        gripperBar = (212, 225, (100 * hand.report()), 25)
        leftGripperBar = (212 + (100 * hand.reportClosed()), 225, 2, 25)
        rightGripperBar = (212 + (100 * hand.reportOpen()), 225, 2, 25)
        pygame.draw.rect(screen, (255, 0, 0), leftBar, 0)
        pygame.draw.rect(screen, (255, 0, 0), rightBar, 0)
        pygame.draw.rect(screen, (255, 0, 0), armBar, 0)
        pygame.draw.rect(screen, (0, 0, 0), upperArmBar, 0)
        pygame.draw.rect(screen, (0, 0, 0), lowerArmBar, 0)
        pygame.draw.rect(screen, (255, 0, 0), gripperBar, 0)
        pygame.draw.rect(screen, (0, 0, 0), leftGripperBar, 0)
        pygame.draw.rect(screen, (0, 0, 0), rightGripperBar, 0)
        pygame.draw.circle(screen, pulseColor, [370, 32], 10)
        pygame.draw.circle(screen, videoColor, [370, 58], 10)
        pygame.display.update()

        time.sleep(0.1)
        if killFlag:
            return

image 用于了解窗口的外观,以帮助您更好地理解代码。

【问题讨论】:

  • time.sleep(0.1) 更改为pygame.time.sleep(100)。如果还有问题,请告诉我。
  • 摆脱return。没有功能。
  • pygame.time.sleep(100) 导致错误“'module' object has no attribute 'sleep'”,return 用于退出线程的 run() 函数。我可能有返回的替代方案,但是有一个函数(只是未显示)返回可以退出。
  • 我的意思是pygame.time.delay(100)

标签: python pygame


【解决方案1】:

很遗憾,我无法运行您发布的代码来测试自己,但我想指出一些可能会有所帮助的事情。首先,这不是杀死程序的正确方法,至少不是我所知道的方式。我在pygame中使用的是:

for event in pygame.event.get():
    if event.type == QUIT:
        pygame.quit()
        sys.exit()

time.sleep(1) 是否在循环结束时尝试控制帧速率?如果是这样,使用 pygame 时钟会更好。在主循环之前初始化一个时钟,如下所示:

clock = pygame.time.Clock()

然后在主循环中使用这个:

clock.tick(60)

这样做的目的是将程序设置为以所需的 fps 运行。在本例中,它设置为 60。

最后,我真的不知道为什么您的窗口在收到鼠标输入后会停止响应,但如果这确实是罪魁祸首,您可以简单地阻止鼠标事件。在你的 while 循环之前试试这个:

pygame.mouse.set_visible(False)
pygame.event.set_blocked(pygame.MOUSEMOTION)
pygame.event.set_blocked(pygame.MOUSEBUTTONDOWN)
pygame.event.set_blocked(pygame.MOUSEBUTTONUP)

这应该忽略来自鼠标的所有输入,您甚至无法在窗口上看到它。

【讨论】:

  • 当所有线程返回时,我添加了pygame.quit()sys.exit()(我在主函数中有join()),尽管sys.exit() 返回“sys is not defined”错误所以也许这就是问题的一部分。
  • 我本打算只做一条评论,但当我不应该输入时,我一直按回车键。 clock.tick() 没有任何改进,我已经尝试过了。尝试禁用鼠标似乎没有任何改变,因为显示器无论如何都不是活动窗口,即使我以不同的方式获得焦点,它也会停止响应。抱歉,它无法运行,这只是整个代码的一部分,它依赖于其他单独的文件、单独的运行程序和一些硬件。我想解决方案需要在其他地方工作,我只是希望有人知道从这么多地方看。
  • 您必须导入系统才能使 sys.exit 工作。没有导入的可以无视,我一般是在我的游戏里导入的。另外,我不完全确定 pygame 支持多线程,这可能是你的问题。
【解决方案2】:

我将此代码移动到 main 而不是线程,它现在可以工作了。我最终确实需要 pygame.event.pump() 行,我现在使用 clock.tick() 进行速率控制,但它在其他方面是相同的,但移动了。显然 pygame 不能很好地处理线程。

感谢所有的帮助,实际的解决方案可能是偶然发现的,但是有一些事情要尝试让我尝试了足够长的时间来尝试我没想到的事情。

【讨论】:

    【解决方案3】:

    事件队列可能已满,无法处理更多事件,因此操作系统说窗口没有响应。

    如果您对任何事件不感兴趣,您应该通过调用pygame.event.clear() 来清除事件队列,但也许您最不想处理pygame.QUIT,因此调用pygame.event.get()(不带参数)也可以解决问题.

    【讨论】:

    • 我在同一个程序的另一个线程中处理事件,所以这不应该是问题,并且试图在不需要它们的线程中获取()它们导致主处理程序错过他们,因为他们已从队列中删除。我正在使用 pump() 以防万一,但在我放入之前它就出现了问题,之后它也没有消失。
    • 你能尝试只在这个线程中读取事件,并通过Queue(或其他线程安全方式)将它们传递给主线程吗?只是在黑暗中拍摄....
    【解决方案4】:

    问题是线程,我有同样的问题,如果我在一个线程中运行 pygame 更新,当我改变焦点时它会锁定,如果我在没有线程的情况下运行它,相同的代码可以正常工作。解决方法是确保仅从您的主原始线程调用“pygame”,然后其他代码可以在其他线程中,但与 pygame 相关的任何内容都应该来自主线程。无论如何,这对我有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-08
      • 2023-03-22
      相关资源
      最近更新 更多