Pygame按钮切换图片报错:TypeError:参数1需为pygame.Surface而非str
Hey there! Let's get that button issue sorted out. You nailed the root cause—you're passing string identifiers like 'default_ip' to your button_img function, but it expects actual pygame.Surface objects (the ones you loaded with pygame.image.load()).
Here's how to fix this cleanly:
1. Use a Dictionary to Map Names to Your Button Surfaces
First, create a dictionary that stores your pre-loaded button surfaces using the name strings (like "default" or "chewbacca") as keys. This lets you look up the right surfaces easily without messing with string concatenation:
# Load your images first (keep this part) default_ap = pygame.image.load('button_menu_ap.png') default_ip = pygame.image.load('button_menu_ip.png') chewbacca_ip = pygame.image.load('button_select_GalaxyWars_chewbacca_ip.png') chewbacca_ap = pygame.image.load('button_select_GalaxyWars_chewbacca_ap.png') # Create a dictionary to map names to surface pairs (ip, ap) button_surfaces = { "default": (default_ip, default_ap), "chewbacca": (chewbacca_ip, chewbacca_ap) }
2. Update the select_p1 Function to Use the Dictionary
Instead of building string names, pull the actual surfaces from the dictionary. Also, note that the pygame.display.update() line after your return won't ever run—return exits the function immediately, so we can remove that:
def select_p1(nombre): # Get the (ip, ap) surface pair from the dictionary nombre_ip, nombre_ap = button_surfaces[nombre] # Call button_img with the actual surfaces, not strings button_img(display_weight/2-300, display_height/2-250, 100, 100, nombre_ip, nombre_ap, select_categoria, 1, nombre) pygame.display.update()
3. Fix a Hidden Bug in select_categoria
You've got a variable named select_categoria inside the function that shares the same name as the function itself. This will cause unexpected behavior when you try to use the loop condition. Rename that variable to something like running:
def select_categoria(num): global gameDisplay, display_weight, display_height # Rename variable to avoid conflict with function name running = True gameDisplay.fill((255,255,255)) while running: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() quit() if event.type == VIDEORESIZE: display_weight = event.w display_height = event.h gameDisplay = pygame.display.set_mode((display_weight, display_height), pygame.RESIZABLE) # Also, make sure button_select_categoria_ip/ap are loaded and defined! button_img(display_weight/2-125, display_height/2-125, 250, 60, button_select_categoria_ip, button_select_categoria_ap, select_GalaxyWars, num) pygame.display.update() clock.tick(15)
Why This Works
The dictionary acts as a lookup table—when you pass 'default' to select_p1, it grabs the default_ip and default_ap surfaces you loaded earlier, not just strings with those names. This gives button_img the pygame.Surface objects it needs to call gameDisplay.blit() correctly.
One last thing: Make sure all your button surface variables (like button_select_categoria_ip) are properly loaded and defined before you use them in select_categoria—otherwise you'll hit another undefined variable error!
内容的提问来源于stack exchange,提问作者Marquetes2

