代码运行正常,正如我预期的那样,但 5 秒后图形显示永远卡住。它没有显示任何错误,什么也没有,只是停止响应。
这是一个模拟一大群物体运动的程序。他们必须像布朗运动一样漫无目的地随机移动。为了做到这一点,我使用 Pygame 将任何对象绘制为随机位置的矩形,为了移动它们,我删除所有内容并再次绘制它们,它们的位置随机改变 1。
我正在使用 pygame 来显示图形。
您能否还为这个问题提出更好的解决方案?
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()
一切都按我的预期工作,但不可避免地会卡住。
更新: 如果我将输入脚本更改为常量数字,则一切正常。所以这个问题在某种程度上与用户界面交互有关。
最佳答案
程序停止是因为 input()
阻塞了程序流。不再发送和处理 PyGame 更新或事件。基本上一切都会停止,等待用户输入。
解决这个问题的最好方法是编写代码,让用户在屏幕上而不是在控制台中进行一些 PyGame 输入。也许制作一个滑块或微调控件来选择数字,或者加号/减号按钮,等等。
或者,程序仍然可以在线程中使用控制台输入,该线程使用 post()
函数将结果发送到主 PyGame 事件循环线程。
我必须承认,这个答案仅具有学术意义,因为使用控制台与 PyGame 窗口一起输入非常难看!
无论如何,这里有一些代码。主 python 窗口每 0.5 秒简单地改变颜色,而用户可以使用标准的 python input()
函数在控制台中输入文本。代码使用它自己的事件枚举类型来发布消息,但这些也可以只是普通数字。
根据 OP,这是有效的,因为 input()
函数是在执行子线程内调用的。这使主线程可以自由地继续处理 PyGame 事件队列,并将更新绘制到窗口。只有一个事件队列/循环很重要(出于超出本答案范围的原因),因此子线程将事件“发布”回主线程,而不是作用于窗口/事件本身。
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()
关于python - 为什么图形窗口在大约 5 秒后卡住?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57718723/