You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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_pos dictionary: 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_oval variable: Keeps track of which oval the user is currently dragging, so we know exactly which one to modify in the move and release methods.
  • pick_oval method: Triggered when the user clicks an oval, using find_closest to grab the ID of the clicked element.
  • Dynamic oval targeting: All operations now use self.active_oval instead of the hardcoded self.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:35:28