Python 3.x Tkinter在每次鼠标单击时创建收缩圆,如何使其与多次单击一起工作?

Python 3.x Tkinter在每次鼠标单击时创建收缩圆,如何使其与多次单击一起工作?,python-3.x,function,tkinter,bind,tkinter-canvas,Python 3.x,Function,Tkinter,Bind,Tkinter Canvas,我正在创建一个简单的程序,通过每次鼠标单击,在每个单击的位置上绘制一个随机颜色的缩小圆圈。每次单击都会创建一个直径为50的圆,该圆立即开始收缩到0。每次单击都应该创建新的收缩圆 但是,在我单击并创建另一个圆后,我的程序停止收缩第一个圆。它仅完全收缩最后创建的圆。其他人都一动不动。 我认为问题在于功能本身。它调用同一个未完成的函数。如何使其运行多次(每次单击时分别执行)?或者局部变量和全局变量有问题吗 以下是我目前的代码: import tkinter import random c = tkin

我正在创建一个简单的程序,通过每次鼠标单击,在每个单击的位置上绘制一个随机颜色的缩小圆圈。每次单击都会创建一个直径为50的圆,该圆立即开始收缩到0。每次单击都应该创建新的收缩圆

但是,在我单击并创建另一个圆后,我的程序停止收缩第一个圆。它仅完全收缩最后创建的圆。其他人都一动不动。 我认为问题在于功能本身。它调用同一个未完成的函数。如何使其运行多次(每次单击时分别执行)?或者局部变量和全局变量有问题吗

以下是我目前的代码:

import tkinter
import random
c = tkinter.Canvas(width = 400, height = 300)
c.pack()

def klik(event):
    global x, y, farba, circ, r
    r = 50      #circle diameter
    x, y = event.x, event.y     #clicked position
    color = '#{:06x}'.format(random.randrange(256 ** 3))        #random  color picker
    circ = c.create_oval(x - r, y - r, x + r, y + r, fill=color)         #print circle
    print(x, y, farba)      #check clicked coordinates, not important
    if r < 50:      #reset size after each circle
        r = 50
    shrink()

def shrink():
    global circ, x, y, r
    print(r)        #check if countdown runs correctly
    if r > 0:
        r -= 1      #diameter shrinking
        c.coords(circ, x-r, y-r, x+r, y+r)      #changing circle size
        c.after(100, shrink)        #timer, size 1pt smaller until size is 0

c.bind('<Button-1>', klik)
tkinter.mainloop()
导入tkinter
随机输入
c=tkinter.Canvas(宽度=400,高度=300)
c、 包()
def klik(事件):
全球x、y、farba、circ、r
r=50#圆直径
x、 y=event.x,event.y#单击位置
颜色='#{:06x}'。格式(random.randrange(256**3))#随机颜色选择器
circ=c.创建椭圆(x-r,y-r,x+r,y+r,填充=颜色)#打印圆
打印(x,y,farba)#检查单击的坐标,不重要
如果r<50:#在每个圆后重置尺寸
r=50
收缩
def shrink():
全球保监会,x,y,r
打印(r)#检查倒计时是否正确运行
如果r>0:
r-=1#直径收缩
c、 坐标(circ,x-r,y-r,x+r,y+r)#改变圆的大小
c、 在(100,收缩)#计时器之后,尺寸减小1pt,直到尺寸为0
c、 绑定(“”,klik)
tkinter.mainloop()

如果将所有内容移动到一个类中,则每个圆都将是自己的实例,不会相互干扰

看看下面修改过的代码版本。这可能不是完美的,但应该是一个很好的基础,为您工作。
import tkinter
import random


c = tkinter.Canvas(width = 400, height = 300)
c.pack()

class create_circles():
    def __init__(self, event):
        self.r = 50
        self.x, self.y = event.x, event.y
        self.color = '#{:06x}'.format(random.randrange(256 ** 3))
        self.circ = c.create_oval(self.x - self.r, self.y - self.r, self.x + self.r, self.y + self.r, fill=self.color)
        self.shrink()

    def shrink(self):
        if self.r > 0:
            self.r -= 1
            c.coords(self.circ, self.x-self.r, self.y-self.r, self.x+self.r, self.y+self.r)
            c.after(100, self.shrink)

c.bind('<Button-1>', create_circles)
tkinter.mainloop()
导入tkinter
随机输入
c=tkinter.Canvas(宽度=400,高度=300)
c、 包()
类create_circles():
定义初始化(自我,事件):
自相关系数r=50
self.x,self.y=event.x,event.y
self.color='#{:06x}'。格式(random.randrange(256**3))
self.circ=c.create_oval(self.x-self.r,self.y-self.r,self.x+self.r,self.y+self.r,fill=self.color)
self.shrink()
def收缩(自):
如果self.r>0:
自相关系数r-=1
c、 坐标(self.circ,self.x-self.r,self.y-self.r,self.x+self.r,self.y+self.r)
c、 之后(100,自我收缩)
c、 绑定(“”,创建_圆)
tkinter.mainloop()
还有另外一种方法,你可以在课外做这件事

您可以使用嵌套函数并避免使用全局函数。问题中的问题实际上是由全局变量引起的

对于非类选项,请尝试下面的代码

import tkinter
import random


c = tkinter.Canvas(width = 400, height = 300)
c.pack()

def klik(event):
    r = 50
    x, y = event.x, event.y
    color = '#{:06x}'.format(random.randrange(256 ** 3))
    circ = c.create_oval(x - r, y - r, x + r, y + r, fill=color)

    def shrink(r, x, y, color, circ):
        if r > 0:
            r -= 1
            c.coords(circ, x-r, y-r, x+r, y+r)
            c.after(100, shrink, r, x, y, color, circ)

    shrink(r, x, y, color, circ)

c.bind('<Button-1>', klik)
tkinter.mainloop()
导入tkinter
随机输入
c=tkinter.Canvas(宽度=400,高度=300)
c、 包()
def klik(事件):
r=50
x、 y=事件.x,事件.y
color='#{:06x}'。格式(random.randrange(256**3))
circ=c.创建椭圆(x-r,y-r,x+r,y+r,fill=color)
def收缩(r、x、y、颜色、循环):
如果r>0:
r-=1
c、 协调(circ,x-r,y-r,x+r,y+r)
c、 之后(100,收缩,r,x,y,颜色,循环)
收缩(r、x、y、颜色、循环)
c、 绑定(“”,klik)
tkinter.mainloop()

如果将所有内容移动到一个类中,则每个圆都将是自己的实例,不会相互干扰

看看下面修改过的代码版本。这可能不是完美的,但应该是一个很好的基础,为您工作。
import tkinter
import random


c = tkinter.Canvas(width = 400, height = 300)
c.pack()

class create_circles():
    def __init__(self, event):
        self.r = 50
        self.x, self.y = event.x, event.y
        self.color = '#{:06x}'.format(random.randrange(256 ** 3))
        self.circ = c.create_oval(self.x - self.r, self.y - self.r, self.x + self.r, self.y + self.r, fill=self.color)
        self.shrink()

    def shrink(self):
        if self.r > 0:
            self.r -= 1
            c.coords(self.circ, self.x-self.r, self.y-self.r, self.x+self.r, self.y+self.r)
            c.after(100, self.shrink)

c.bind('<Button-1>', create_circles)
tkinter.mainloop()
导入tkinter
随机输入
c=tkinter.Canvas(宽度=400,高度=300)
c、 包()
类create_circles():
定义初始化(自我,事件):
自相关系数r=50
self.x,self.y=event.x,event.y
self.color='#{:06x}'。格式(random.randrange(256**3))
self.circ=c.create_oval(self.x-self.r,self.y-self.r,self.x+self.r,self.y+self.r,fill=self.color)
self.shrink()
def收缩(自):
如果self.r>0:
自相关系数r-=1
c、 坐标(self.circ,self.x-self.r,self.y-self.r,self.x+self.r,self.y+self.r)
c、 之后(100,自我收缩)
c、 绑定(“”,创建_圆)
tkinter.mainloop()
还有另外一种方法,你可以在课外做这件事

您可以使用嵌套函数并避免使用全局函数。问题中的问题实际上是由全局变量引起的

对于非类选项,请尝试下面的代码

import tkinter
import random


c = tkinter.Canvas(width = 400, height = 300)
c.pack()

def klik(event):
    r = 50
    x, y = event.x, event.y
    color = '#{:06x}'.format(random.randrange(256 ** 3))
    circ = c.create_oval(x - r, y - r, x + r, y + r, fill=color)

    def shrink(r, x, y, color, circ):
        if r > 0:
            r -= 1
            c.coords(circ, x-r, y-r, x+r, y+r)
            c.after(100, shrink, r, x, y, color, circ)

    shrink(r, x, y, color, circ)

c.bind('<Button-1>', klik)
tkinter.mainloop()
导入tkinter
随机输入
c=tkinter.Canvas(宽度=400,高度=300)
c、 包()
def klik(事件):
r=50
x、 y=事件.x,事件.y
color='#{:06x}'。格式(random.randrange(256**3))
circ=c.创建椭圆(x-r,y-r,x+r,y+r,fill=color)
def收缩(r、x、y、颜色、循环):
如果r>0:
r-=1
c、 协调(circ,x-r,y-r,x+r,y+r)
c、 之后(100,收缩,r,x,y,颜色,循环)
收缩(r、x、y、颜色、循环)
c、 绑定(“”,klik)
tkinter.mainloop()

如前所述,您不需要类来解决此问题,也不需要嵌套函数。正如@liorahaydon所暗示的,关键是您需要使用局部变量,而不是全局变量:

import tkinter as tk
from random import randrange

def klik(event):
    r = 50  # circle radius
    x, y = event.x, event.y  # clicked position
    color = '#{:06x}'.format(randrange(256 ** 3))  # random color picker
    c = canvas.create_oval(x - r, y - r, x + r, y + r, fill=color)  # print circle
    canvas.after(100, shrink, c, x, y, r)

def shrink(c, x, y, r):
    if r > 0:
        r -= 1  # radius shrinking
        canvas.coords(c, x - r, y - r, x + r, y + r)  # changing circle size
        canvas.after(100, shrink, c, x, y, r)  # timer, size 1pt smaller until size is 0

canvas = tk.Canvas(width=400, height=300)
canvas.pack()
canvas.bind('<Button-1>', klik)

tk.mainloop()
将tkinter作为tk导入
从随机输入范围
def klik(事件):
r=50#圆半径
x、 y=event.x,event.y#单击位置
颜色=“#{:06x}”。格式(随机范围(256**3))#随机颜色选择器
c=画布。创建椭圆(x-r,y-r,x+r,y+r,填充=颜色)#打印圆
画布后(100,收缩,c,x,y,r)
def收缩(c、x、y、r):
如果r>0:
r-=1#半径收缩
canvas.coords(c,x-r,y-r,x+r,y+r)#改变圆的大小
画布。在(100,收缩,c,x,y,r)#计时器之后,尺寸变小1磅,直到尺寸为0
画布=tk.canvas(宽度=400,高度=300)
canvas.pack()
画布绑定(“”,klik)
tk.mainloop()
如注释所示