发布
社区首页 >问答首页 >为什么图形窗口在大约5秒后就会冻结?

为什么图形窗口在大约5秒后就会冻结?
EN

Stack Overflow用户
提问于 2019-08-29 23:15:36
回答 1查看 139关注 0票数 4

代码运行正常,如我所料,但5秒后,图形显示将永久冻结。它没有错误,没有,只是停止了响应。

这是一个用来模拟一大群物体运动的程序。在无目标的情况下,就像布朗运动一样,它们必须随意移动。为了做到这一点,我使用Pygame绘制任意对象作为任意位置的矩形,为了移动它们,我删除了所有的东西,然后再绘制它们,它们的位置被随机更改为1。我正在使用吡咯来显示图形。你能不能为这个问题提出一个更好的解决方案?

代码语言:javascript
代码运行次数:0
复制
import pygame, random, sys, time, numpy
from pygame.locals import *

black = (0,0,0)
white = (255,255,255)

clock = pygame.time.Clock()

class people():

    def __init__(self):

        screen = pygame.display.get_surface()

        self.x = random.randint(0, 800)
        self.y = random.randint(0, 600)

    def move(self):
        self.x += random.randint(-1, 1)
        self.y += random.randint(-1, 1)
        if self.x < 0:
            self.x = 0
        if self.x > 800:
            self.x = 800
        if self.y < 0:
            self.y = 0
        if self.y > 600:
            self.y = 600

    def place(x, y):
        screen = pygame.display.get_surface()
        pygame.draw.rect(screen, black, [x, y, 10, 10])

def main():
    # Initialise screen
    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    pygame.display.set_caption('Test')

    peoples = []

    chosepopul = 1

    while chosepopul == 1:
        try:
            population = abs(int(input("How many people would you like to have")))
            chosepopul = 0
        except:
            print("Number, please")    

    for i in range(population):
        peoples.append(people())

    while True:

        screen.fill(white)

        for obj in peoples:

            people.place(obj.x, obj.y)

            people.move(obj)

        pygame.display.update()
        clock.tick(60)

if __name__ == '__main__':
    main()

pygame.quit()
quit()

一切都如我所料,但不可避免地会结冰。

更新:如果我将输入脚本更改为常量,则一切都正常工作。因此,这个问题在某种程度上与用户界面交互有关。

EN

回答 1

Stack Overflow用户

发布于 2019-08-30 00:00:30

程序停止,因为input()阻止了程序流。不再发送和处理进一步的PyGame更新或事件。基本上,一切都会停止,等待用户输入。

解决这个问题的最好方法是编写代码,这样用户就可以在屏幕上输入一些PyGame,而不是在控制台中。也许做一个滑块或旋转控件来选择数字,或者加/减按钮,什么的。

或者,程序仍然可以在使用post()函数将结果发送到主PyGame事件循环线程的线程中使用控制台输入。

我必须承认,这个答案只是学术上的兴趣,因为使用控制台与PyGame窗口一起输入是非常丑陋的!

总之,这是一些代码。主python窗口只需每0.5秒更改一次颜色,而用户可以使用标准python input()函数在控制台中输入文本。代码使用它自己的事件枚举类型来发布消息,但这些也可能只是普通的数字。

按照OP,这是可行的,因为input()函数是在执行的子线程中调用的。这样,主线程就可以继续处理PyGame事件队列,并对窗口进行更新。只有一个事件队列/循环(原因超出了这个答案的范围)是很重要的,因此子线程将事件“发布”回主线程,而不是对窗口/事件本身采取行动。

代码语言:javascript
代码运行次数:0
复制
import threading
import pygame
import enum

# Window size
WINDOW_WIDTH  = 200
WINDOW_HEIGHT = 200

DARK    = (  50, 50, 50 )
WHITE   = ( 255,255,255 )
RED     = ( 255, 55, 55 )
GREEN   = (   5,255, 55 )
BLUE    = (   5, 55,255 )


colour_cycle = [ DARK, WHITE, RED, GREEN, BLUE ]


class UserEvents( enum.IntEnum ):
    CLIENT_NUMBER = pygame.USEREVENT + 1
    CLIENT_QUIT   = pygame.USEREVENT + 2
    # ...



class ConsoleInputThread( threading.Thread ):
    """ A thread that handles user input on the console.
        Waits for user input, then posts messages
        to the main PyGame thread for processing """
    def __init__( self, prompt ):
        threading.Thread.__init__(self)
        self.daemon         = True # exit with parent
        self.done           = False
        self.prompt         = prompt

    def stop( self ):
        self.done = True

    def run( self ):
        """ Loops until the user hangs-up """
        while ( not self.done ):
            # Get some input from the user
            user_input = input( self.prompt ).strip()
            new_event = None
            if ( user_input == 'quit' ):
                new_event = pygame.event.Event( UserEvents.CLIENT_QUIT, { } )
            else:
                try:
                    user_input = int( user_input )
                    new_event = pygame.event.Event( UserEvents.CLIENT_NUMBER, { "value":user_input } )
                except:
                    print( "Syntax Error" )
            # If we received valid input post it to the main thread
            if ( new_event ):
                pygame.event.post( new_event )




###
### MAIN
###

# Create the window
pygame.init()
pygame.display.set_caption("Socket Messages")
SURFACE = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE
WINDOW  = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), SURFACE )


# Start the console-input thread
input_thread = ConsoleInputThread( "How many people would you like to have: " )
input_thread.start()

# Main paint / update / event loop
done = False
clock = pygame.time.Clock()
colour_index = 0
while ( not done ):

    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True

        elif ( event.type == UserEvents.CLIENT_QUIT ):
            print("\nCLIENT ASKED TO QUIT " )
            done = True

        elif ( event.type == UserEvents.CLIENT_NUMBER ):
            print( "\nVALUE WAS INPUT: %d " % ( event.value, ) )


    WINDOW.fill( colour_cycle[colour_index] )
    # rotate the colours, just so the screen changes
    colour_index += 1
    if ( colour_index >= len( colour_cycle ) ):
        colour_index = 0

    pygame.display.flip()

    clock.tick_busy_loop(2)  # NOTE: 2 frames per second, no flashy-flashy

input_thread.stop()
pygame.quit()
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57718723

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档