在Python tkinter中移动更多对象

时间:2018-01-13 20:01:17

标签: python events tkinter move

我制作简单的游戏 - 有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()

1 个答案:

答案 0 :(得分:2)

我绑定了三个方法

  • <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]