В комментариях @Fredrik вы, вероятно, хотите использовать поток, а не отдельный процесс.Потоки имеют общий доступ к памяти, переменным и т. Д., В то время как отдельные процессы имеют отдельную копию с того места, где был запущен дочерний процесс.
Так что, если я могу перефразировать ваш вопрос:
Как мне рисовать на экране пигмея из нескольких потоков?
И на что краткий ответ: «Вы не делаете».
Как правило, с событиями, управляемыми,основанные на окнах рабочие столы, программы имеют единый поток, который управляет взаимодействием с пользователем, включая обработку ввода и вывода на экран.Конечно, вы могли бы быть в состоянии вызвать screen.blit(...)
из нескольких потоков из-за Python GIL , но это не очень хороший путь проектирования.
Но!Это не означает, что другие потоки и процессы не могут создавать контент для дисплея, но затем передать его потоку основного обработчика для этого последнего бита на экран, так как же?
ОтдельноПроцессы python могут взаимодействовать друг с другом с помощью Client
и Listener
pipe (это тоже касается GIL), и, как уже упоминалось ранее, отдельные потоки могут просто совместно использовать память.
Воткусочек кода, который отображает фоновое изображение вне экрана, а затем отправляет событие в главный поток, когда каждое новое обновление готово.Очевидно, что это тривиальное использование потока, но если бы процесс обновления занимал больше времени, он подходил бы лучше.
Функция потока изначально создает поверхность Pygame, делая ее похожей на 8-битное отображение чернильной черноты пространства.Затем навсегда перемещается по изображению, отправляя копию в виде Pygame.Event в главный поток через очередь событий.Основной поток видит это событие и обновляет его фоновое изображение.
Результат довольно резкий, но это потому, что я помещаю поток в спящий режим на 500 мс на каждой итерации, чтобы немного его замедлить.
import threading
import pygame
import random
import time
import sys
# Window size
WINDOW_WIDTH=400
WINDOW_HEIGHT=400
DARK_GREY = ( 50, 50, 50 )
SPACE_BLACK = ( 0, 0, 77 )
STAR_WHITE = ( 255, 252, 216 )
### Thread that paints a background image to an off-screen surface
### then posts an event to the main loop when the image is ready
### for displaying.
class BackgroundDrawThread( threading.Thread ):
def __init__( self ):
threading.Thread.__init__(self)
self.daemon = True # exit with parent
self.sleep_event = threading.Event()
self.ofscreen_block = pygame.Surface( ( WINDOW_WIDTH, WINDOW_HEIGHT ) )
self.pan_pixels = 5
def makeSpace( self ):
""" Make a starry background """
# Inky blackness of space
self.ofscreen_block.fill( SPACE_BLACK )
# With some (budget-minded) stars
for i in range( 80 ):
random_pixel = ( random.randrange( WINDOW_WIDTH ), random.randrange( WINDOW_HEIGHT ) )
self.ofscreen_block.set_at( random_pixel, STAR_WHITE )
def panSpace( self ):
""" Shift space left, by some pixels, wrapping the image """
rect_to_move = [0, 0, self.pan_pixels, WINDOW_HEIGHT-1]
lost_part = self.ofscreen_block.subsurface( rect_to_move ).copy()
self.ofscreen_block.scroll( dx=-self.pan_pixels, dy=0)
self.ofscreen_block.blit( lost_part, ( WINDOW_WIDTH-1-self.pan_pixels,0) )
def run( self ):
""" Do Forever (or until interuppted) """
# Make the space backdrop
self.makeSpace()
while ( True ):
if ( True == self.sleep_event.wait( timeout=0.5 ) ):
break # sleep was interrupted by self.stop()
else:
# Rotate space a bit
self.panSpace()
# Message the main-thread that space has been panned.
new_event_args = { "move": self.pan_pixels, "bitmap": self.ofscreen_block.copy() }
new_event = pygame.event.Event( pygame.USEREVENT + 1, new_event_args )
pygame.event.post( new_event )
def stop( self ):
self.sleep_event.set() # interrupt the wait
self.join()
### MAIN
pygame.init()
pygame.display.set_caption("Threaded Paint")
WINDOW = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE )
# Start the render-my-background thread
thread1 = BackgroundDrawThread()
thread1.start()
background = None
# Main paint / update / event loop
done = False
clock = pygame.time.Clock()
while ( not done ):
# Handle Events
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
done = True
elif ( event.type == pygame.USEREVENT + 1 ):
background = event.bitmap
print( "Space folded by %d pixels" % ( event.move ) )
# Paint the window
if ( background != None ): # wait for the first backgroun to be ready message
WINDOW.blit( background, (0,0) )
pygame.display.flip()
# Max FPS
clock.tick_busy_loop(60)
thread1.stop()
pygame.quit()
Хм, глядя на анимацию, мне кажется, что у меня ошибка "1 к 1" при сворачивании пространства.Я предполагаю, что коду нужно больше spice .