在 Python tkinter 中移动更多对象

Moving more objects in Python tkinter

我正在制作简单的游戏 - 有 8 个椭圆,它们应该是可点击和可移动的。单击椭圆后,椭圆跟随光标。目标是将椭圆变成矩形,如果在矩形中松开鼠标按钮,椭圆就会消失。如果您在矩形外释放鼠标按钮,椭圆应该出现在它的初始位置。我制作了这个程序并且它有效,但只适用于一个椭圆形。我需要它适用于所有椭圆。这是我的代码,请问您知道要更改什么吗?

import tkinter, random

class Desktop:

    array = [(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)
        for i in range(len(self.array)):
            self.__dict__[f'oval{i}'] = self.canvas.create_oval(self.array[i], fill='brown',tags='id')
        self.canvas.tag_bind('id','<B1-Motion>',self.move)
        self.canvas.tag_bind('id','<ButtonRelease-1>',self.release)

    def move(self, event):
        self.canvas.coords(self.oval0,event.x-10,event.y-10,event.x+10,event.y+10)

    def release(self, event):
        if event.x>100 and event.x<300 and event.y>250 and event.y<350:
            self.canvas.delete(self.oval0)
        else:
            self.canvas.coords(self.oval0,self.array[0])


d = Desktop()

我绑定了三个方法

  • <ButtonPress-1> 获取点击项目的 ID 并分配给 self.selected
  • <B1-Motion> 使用 self.selected
  • 移动项目
  • <ButtonRelease-1> 使用 self.selected
  • 释放或删除移动的项目

代码

import tkinter as tk
import random

class Desktop:

    array = [(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, master):
        self.canvas = tk.Canvas(master, width=400, height=400)
        self.canvas.pack()

        self.canvas.create_rectangle(100, 250, 300, 350)

        # to keep all IDs and its start position
        self.ovals = {}

        for item in self.array:
            # create oval and get its ID
            item_id = self.canvas.create_oval(item, fill='brown', tags='id')
            # remember ID and its start position
            self.ovals[item_id] = item

        self.canvas.tag_bind('id', '<ButtonPress-1>', self.start_move)
        self.canvas.tag_bind('id', '<B1-Motion>', self.move)
        self.canvas.tag_bind('id', '<ButtonRelease-1>', self.stop_move)

        # to remember selected item
        self.selected = None

    def start_move(self, event):
        # find all clicked items
        self.selected = self.canvas.find_overlapping(event.x, event.y, event.x, event.y)
        # get first selected item
        self.selected = self.selected[0]

    def move(self, event):
        # move selected item
        self.canvas.coords(self.selected, event.x-10, event.y-10, event.x+10,event.y+10)

    def stop_move(self, event):
        # delete or release selected item
        if 100 < event.x < 300 and 250 < event.y < 350:
            self.canvas.delete(self.selected)
            del self.ovals[self.selected]
        else:
            self.canvas.coords(self.selected, self.ovals[self.selected])
        # clear it so you can use it to check if you are draging item
        self.selected = None

root = tk.Tk()
d = Desktop(root)
root.mainloop()

编辑: 使用 event.widget.find_withtag("current")[0] 我可以获得第一个选择的项目,我可以跳过 <ButtonPress-1>.

import tkinter as tk
import random

class Desktop:

    array = [(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, master):
        self.canvas = tk.Canvas(master, width=400, height=400)
        self.canvas.pack()

        self.canvas.create_rectangle(100, 250, 300, 350)

        # to keep all IDs and its start position
        self.ovals = {}

        for item in self.array:
            # create oval and get its ID
            item_id = self.canvas.create_oval(item, fill='brown', tags='id')
            # remember ID and its start position
            self.ovals[item_id] = item

        self.canvas.tag_bind('id', '<B1-Motion>', self.move)
        self.canvas.tag_bind('id', '<ButtonRelease-1>', self.stop_move)

    def move(self, event):
        # get selected item
        selected = event.widget.find_withtag("current")[0]

        # move selected item
        self.canvas.coords(selected, event.x-10, event.y-10, event.x+10,event.y+10)

    def stop_move(self, event):
        # get selected item
        selected = event.widget.find_withtag("current")[0]

        # delete or release selected item
        if 100 < event.x < 300 and 250 < event.y < 350:
            self.canvas.delete(selected)
            del self.ovals[selected]
        else:
            self.canvas.coords(selected, self.ovals[selected])

root = tk.Tk()
d = Desktop(root)
root.mainloop()

编辑: 添加了 del self.ovals[selected]