簡體   English   中英

pygame “畫圖”程序 - 在 canvas 上繪制空矩形

[英]pygame “Paint” program - drawing empty rectangle on canvas

所以我正在使用 pygame (我是全新的)制作一個類似 MS-Paint 的程序,到目前為止進展順利,除了我遇到的這個煩人的問題。 我希望用戶能夠通過沿 canvas 拖動鼠標來繪制矩形,類似於您在 MS-Paint 中的操作,並且我希望它看起來好像矩形在“移動”只要鼠標是被拖着。 我設法讓它完美地工作但效率低下,直到我被告知我應該使用其他一些 pygame 方法來提高效率。 所以我做到了,但我無法解決的一個問題是矩形的先前圖像仍保留在屏幕上。 像這樣:左上角是我開始繪制的地方 這是我的代碼的相關部分:

        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()但它沒有用(我想我不完全理解它是如何工作的)。 無論如何,如果有人有任何想法,我很樂意聽到建議:)

問題是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))

然后似乎在讀取save_lastscreen被臨時查看,因為它被引用了。 最后寫入screen失敗。

但是您可以通過.blit()直接將screen區域復制到screen來解決此問題。 不要創建次表面,只需注意矩形區域( pygame.Rect )並將區域從screen Surface復制到screen上的另一個 position 。 例如:

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))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM