因此,我正在使用pygame(我是全新的)制作类似于MS-Paint的程序,到目前为止进展顺利,除了我遇到的这个烦人的问题。 我希望用户能够通过在画布上拖动鼠标来绘制矩形,这与您在MS-Paint中的操作类似,并且我希望它看起来就像矩形在“移动”(只要鼠标一直在移动)被拖。 在设法告知我应该使用其他一些pygame方法使其更高效之前,我设法使其完美且效率低下。所以我做到了,而我无法解决的一个问题是,矩形的先前图像仍保留在屏幕上。像这样: Top-left is where I started to draw 这是我的代码的相关部分:
if canvas.collidepoint(cursor) and pygame.mouse.get_pressed()[0] and mode == 'Square' and not draw_square:
start_x, start_y = find_pixel(mouse_x, mouse_y)
width, height = find_pixel(mouse_x, mouse_y)
save_last = screen.subsurface(start_x, start_y, width - start_x, height - start_y)
square = pygame.draw.rect(screen, current_color, (start_x, start_y, width - start_x, height - start_y), 5)
temp_square = square
draw_square = True
if draw_square and canvas.collidepoint(cursor) and pygame.mouse.get_pressed()[0]:
# Mouse is being held down outside canvas, show square progress
prev_width, prev_height = width, height
save_last = screen.subsurface(temp_square)
width, height = find_pixel(mouse_x, mouse_y)
if width != prev_width or height != prev_height:
square = temp_square.inflate(width - start_x, height - start_y)
square.topleft = start_x, start_y
pygame.draw.rect(screen, current_color, square, 5)
if not canvas.collidepoint(cursor) and draw_square:
# Mouse is being held down outside canvas, show square progress
width, height = find_pixel(mouse_x, mouse_y)
if width < 150: # Cursor is left of the canvas
width = 150
if width > 980: # Cursor is right of the canvas
width = 980
if height < 20: # Cursor is above the canvas
height = 20
if height > 580: # Cursor if below the canvas
height = 580
square = temp_square.inflate(width - start_x, height - start_y)
square.topleft = start_x, start_y
pygame.draw.rect(screen, current_color, square, 5)
if draw_square and not pygame.mouse.get_pressed()[0]:
draw_square = False
pygame.display.flip()
我尝试将save_last
拖到屏幕上,但这给了我这个错误:
Traceback (most recent call last):
File "C:/Users/yargr/PycharmProjects/Paint/PaintApp.py", line 548, in <module>
main()
File "C:/Users/yargr/PycharmProjects/Paint/PaintApp.py", line 435, in main
screen.blit(save_last, (mouse_x, mouse_y))
pygame.error: Surfaces must not be locked during blit
我尝试使用screen.unlock()
,但没有用(我想我还不完全了解它是如何工作的)。无论如何,如果有人有什么想法,我很想听听建议:)
答案 0 :(得分:0)
问题在于save_last
是屏幕的一个子表面,原因是
save_last = screen.subsurface(start_x, start_y, width - start_x, height - start_y)
分别
save_last = screen.subsurface(temp_square)
subsurface()
创建一个引用另一个表面的表面。新的Surface与另一个父级共享其像素。新表面没有自己的数据。
如果愿意
screen.blit(save_last, (mouse_x, mouse_y))
然后,当读取screen
时,似乎save_last
会临时出现,因为已对其进行了引用。最后写入screen
失败。
但是您可以通过.blit()
将screen
的区域直接复制到screen
来解决此问题。不要创建地下表面,只需注意矩形区域(pygame.Rect
)并将该区域从screen
Surface
复制到screen
上的另一个位置。例如:
save_rect = pygame.Rect(start_x, start_y, width - start_x, height - start_y)
# [...]
save_rect = pygame.Rect(temp_square)
# [...]
screen.blit(screen, (mouse_x, mouse_y), area=save_rect)
或者,您也可以创建矩形区域的副本并将blit
的副本复制到screen
:
save_rect = pygame.Rect(start_x, start_y, width - start_x, height - start_y)
save_last = pygame.Surface(save_rect.size)
save_last.blit(screen, (0, 0), save_rect)
# [...]
save_rect = pygame.Rect(temp_square)
save_last = pygame.Surface(save_rect.size)
save_last.blit(screen, (0, 0), save_rect)
# [...]
screen.blit(save_last, (mouse_x, mouse_y))