Python Tkinter实现多个可点击可移动椭圆的游戏功能优化求助
Fixing Multi-Oval Drag & Release in Your Tkinter Game
Hey, I see the issue here—right now your code only ever references self.oval0 in the move and release methods, so no matter which oval you click, it's only moving the first one. Let's adjust this to track the currently selected oval and handle all 8 of them properly.
Here's the updated code with clear explanations of the key changes:
import tkinter, random class Desktop: # Store initial oval positions in a list oval_positions = [ (50,50,70,70), (100,50,120,70), (150,50,170,70), (150,100,170,120), (150,150,170,170), (100,150,120,170), (50,150,70,170), (50,100,70,120) ] def __init__(self): self.canvas = tkinter.Canvas(width=400, height=400) self.canvas.pack() self.canvas.create_rectangle(100,250,300,350) # Create a dictionary to map each oval's ID to its original position self.oval_id_to_pos = {} for pos in self.oval_positions: oval_id = self.canvas.create_oval(pos, fill='brown', tags='id') self.oval_id_to_pos[oval_id] = pos # Track which oval is currently being dragged self.active_oval = None # Bind events: first capture the click to select an oval self.canvas.tag_bind('id', '<ButtonPress-1>', self.pick_oval) self.canvas.tag_bind('id', '<B1-Motion>', self.move) self.canvas.tag_bind('id', '<ButtonRelease-1>', self.release) def pick_oval(self, event): # Get the ID of the oval the user clicked on self.active_oval = self.canvas.find_closest(event.x, event.y)[0] def move(self, event): if self.active_oval: # Update the active oval's position to follow the cursor self.canvas.coords(self.active_oval, event.x-10, event.y-10, event.x+10, event.y+10) def release(self, event): if not self.active_oval: return # Check if the release happened inside the target rectangle if 100 < event.x < 300 and 250 < event.y < 350: self.canvas.delete(self.active_oval) del self.oval_id_to_pos[self.active_oval] else: # Reset the oval to its original position self.canvas.coords(self.active_oval, self.oval_id_to_pos[self.active_oval]) # Clear the active oval selection self.active_oval = None d = Desktop() tkinter.mainloop() # Don't forget this line to start the Tkinter event loop!
Key Changes Breakdown:
self.oval_id_to_posdictionary: This links each oval's unique ID (assigned by Tkinter when created) to its starting position, so we can easily reset any oval later.self.active_ovalvariable: Keeps track of which oval the user is currently dragging, so we know exactly which one to modify in themoveandreleasemethods.pick_ovalmethod: Triggered when the user clicks an oval, usingfind_closestto grab the ID of the clicked element.- Dynamic oval targeting: All operations now use
self.active_ovalinstead of the hardcodedself.oval0, so every oval gets proper interaction. - Added
tkinter.mainloop(): Your original code was missing this critical line, which starts Tkinter's event handling and makes the window responsive.
Now every oval can be clicked, dragged, and will either disappear (if released inside the rectangle) or snap back to its starting spot (if released outside).
内容的提问来源于stack exchange,提问作者Jozko
相关产品推荐
相关产品推荐

