Pygame报错:argument 1 must be pygame.Surface, not pygame.Rect 如何解决?铅笔点击类游戏开发问题排查
Hey there! Let's break down why your Pygame window isn't showing content and fix that error once and for all.
The Root Cause
That error message tells you exactly what's wrong: TypeError: argument 1 must be pygame.Surface, not pygame.Rect. Here's the breakdown:
- When you use
font.render(), it creates a Surface—this is the actual text image you want to draw on the screen. - The
screen.blit()method needs two arguments: first the Surface to render, then the position (either a coordinate tuple or a Rect object). - You accidentally swapped these: you passed the Rect (from
PENCILS.get_rect()) as the first argument instead of the Surface itself. That's why Pygame throws the type error.
Step-by-Step Fixes
Let's correct your code and fix a couple of small logic issues too:
Fix the
screen.blit()call order
Pass the Surface first, then use the Rect to define where it should be drawn.Fix the "Per Second" text display
You're currently renderinguser.pencilsfor both lines—you meant to useuser.pencilspersecondfor the second line to show the passive gain.Fix the click increment logic
Your click handler usesuser.score +=1, but yourPlayerclass only has apencilsattribute. Change that touser.pencils +=1to actually increase your pencil count.Add screen clearing and display updates
Without clearing the screen each frame, old content will stick around, and without updating the display, nothing will show up even after fixing the blit error.
Corrected Code Snippet
Here's the updated version of your relevant code with all fixes applied:
class pencilsDisplay(): def __init__(self, x, y): self.x = x self.y = y self.height = 100 self.length = 100 def draw(self): font = pygame.font.Font('font/Gidole-Regular.ttf', 24) # Render text surfaces first PENCILS = font.render(f'{int(user.pencils)} Pencils', True, WHITE) # Fixed: Use pencilspersecond instead of pencils for the second line PENCILSPERSECOND = font.render(f'Per Second: {int(user.pencilspersecond)}', True, WHITE) # Get rects for positioning, then blit the surfaces in the correct order pencil_rect = PENCILS.get_rect(center=(int(self.x + self.length/2), int(self.y + 20))) screen.blit(PENCILS, pencil_rect) # Adjust y-position to prevent overlapping text pps_rect = PENCILSPERSECOND.get_rect(center=(int(self.x + self.length/2), int(self.y + 50))) screen.blit(PENCILSPERSECOND, pps_rect) class Player: def __init__(self): self.pencils = 0 self.pencilspersecond = 0 user = Player() pencil = MainPencil(100,100) pencil_display = pencilsDisplay(100,0) def draw(): # Clear the screen with a background color (black here) screen.fill((0, 0, 0)) pencil.draw() pencil_display.draw() # Update the display to show all drawn elements pygame.display.flip() running = True while running: for event in pygame.event.get(): if event.type == pygame.MOUSEBUTTONDOWN: mouse_pos = event.pos if pencil.collidepoint(mouse_pos): # Fixed: Increment pencils instead of non-existent score user.pencils += 1 pencil.animation_state = 1 if event.type == pygame.QUIT: running = False draw()
Quick Tips for Pygame Newbies
- Always clear the screen with
screen.fill()at the start of yourdraw()function to avoid smearing old frames. - Call
pygame.display.flip()orpygame.display.update()after drawing everything to refresh the window. - Double-check attribute names (like
pencilsvsscore) to avoid unexpected AttributeErrors later.
内容的提问来源于stack exchange,提问作者Jack Doherty

