python 中有没有办法在几秒钟后隐藏 canvas?

is there a way in python to hide canvas after few second?

我正在尝试绘制 4 个球体,这些球体会在屏幕上停留几秒钟然后消失。每个球体下方都会出现一个计时器,显示在它消失前还剩多少秒。问题是我在理论上设法做到的是可行的,但没有按应有的方式出现在屏幕上。 我究竟做错了什么?有没有办法做到这一点? 抱歉,英语可能很糟糕,但我正在使用 google 翻译

import tkinter as tk
from tkinter import Tk, Frame, Canvas, BOTH

class Draw(Frame):
    def __init__(self, parent):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.pack(fill=BOTH, expand=1)
        canvas = Canvas(self)
        heightpx=Tk.winfo_screenheight(self)
        widthpx=Tk.winfo_screenwidth(self)
        distOrizPx=int(widthpx/4)
        distVertPx=int(heightpx/4)
        radiusPx=50

        self.ball01 = canvas.create_oval(distOrizPx-radiusPx, distVertPx-radiusPx, distOrizPx+radiusPx, distVertPx+radiusPx, fill="blue", width=0)
        self.ball02 = canvas.create_oval(widthpx-distOrizPx-radiusPx, distVertPx-radiusPx, widthpx-distOrizPx+radiusPx, distVertPx+radiusPx, fill="red", width=0)
        self.ball03 = canvas.create_oval(distOrizPx-radiusPx, heightpx-distVertPx-radiusPx, distOrizPx+radiusPx, heightpx-distVertPx+radiusPx, fill="green", width=0)
        self.ball04 = canvas.create_oval(widthpx-distOrizPx-radiusPx, heightpx-distVertPx-radiusPx, widthpx-distOrizPx+radiusPx, heightpx-distVertPx+radiusPx, fill="yellow", width=0)
        canvas.pack(fill=BOTH, expand=1)
        self.timer(distOrizPx-radiusPx, distVertPx+radiusPx) 
        canvas.delete(self.ball01)
        self.timer(widthpx-distOrizPx-radiusPx, distVertPx+radiusPx)
        canvas.delete(self.ball02)
        self.timer(distOrizPx-radiusPx, heightpx-distVertPx+radiusPx)
        canvas.delete(self.ball03)
        self.timer(widthpx-distOrizPx-radiusPx, heightpx-distVertPx+radiusPx)
        canvas.delete(self.ball04)

    def timer(self,posx,posy):
        self.seconds = 3
        self.label= tk.Label(text="%i s" % self.seconds, font="Arial 30")
        self.label.place(x=posx, y=posy)
        self.label.after(1000, func=self.refresh_label())

    def refresh_label(self):
        self.seconds -= 1
        self.label.configure(text="%i s" % self.seconds)
        if self.seconds>-1:
            self.label.after(1000, self.refresh_label)
        elif self.seconds==-1:
            self.label.destroy()

class Ball:
    def __init__(self, master):
        master.title("Ball")
        master.geometry("200x200")
        master.state('zoomed')
        self.master = master
        self.draw = Draw(master)

if __name__ == "__main__":
    master = tk.Tk() 
    pyBall = Ball(master)
    master.mainloop()

你有两个问题。

首先:你同时创建和销毁球,所以你看不到球。你必须使用 after() 到 运行 函数,它会在几秒钟后删除球。您可以在 label.destroy() 之后删除行中的球,这会在几秒后删除标签。

其次: 你展示了 4 个球,但你只有一个 self.label 和一个 self.seconds,而且所有的球都使用它们。每个球需要拥有label和拥有seconds来计算和显示时间。

I 运行 timer 带有参数 secondsball 所以每个计时器都有时间变量,它知道以后要删除哪个球。

Timer 运行s refresh_label 也得到参数 label 所以每个 timer 使用自己的 label, 自己的 second,并拥有 ball.

import tkinter as tk
from tkinter import Tk, Frame, Canvas, BOTH

class Draw(Frame):
    def __init__(self, master):
        super().__init__(master)
        self.initUI()

    def initUI(self):
        self.pack(fill=BOTH, expand=1)

        self.canvas = Canvas(self, bg='red')
        self.canvas.pack(fill=BOTH, expand=1)

        heightpx = Tk.winfo_screenheight(self)
        widthpx = Tk.winfo_screenwidth(self)
        distOrizPx = int(widthpx/4)
        distVertPx = int(heightpx/4)
        radiusPx = 50

        self.ball01 = self.canvas.create_oval(distOrizPx-radiusPx, distVertPx-radiusPx, distOrizPx+radiusPx, distVertPx+radiusPx, fill="blue", width=1)
        self.ball02 = self.canvas.create_oval(widthpx-distOrizPx-radiusPx, distVertPx-radiusPx, widthpx-distOrizPx+radiusPx, distVertPx+radiusPx, fill="red", width=0)
        self.ball03 = self.canvas.create_oval(distOrizPx-radiusPx, heightpx-distVertPx-radiusPx, distOrizPx+radiusPx, heightpx-distVertPx+radiusPx, fill="green", width=0)
        self.ball04 = self.canvas.create_oval(widthpx-distOrizPx-radiusPx, heightpx-distVertPx-radiusPx, widthpx-distOrizPx+radiusPx, heightpx-distVertPx+radiusPx, fill="yellow", width=0)

        self.timer(distOrizPx-radiusPx, distVertPx+radiusPx, 17, self.ball01) 
        self.timer(widthpx-distOrizPx-radiusPx, distVertPx+radiusPx, 7, self.ball02) 
        self.timer(distOrizPx-radiusPx, heightpx-distVertPx+radiusPx, 7, self.ball03) 
        self.timer(widthpx-distOrizPx-radiusPx, heightpx-distVertPx+radiusPx, 13, self.ball04) 

    def timer(self, posx, posy, seconds, ball):
        label = tk.Label(self, text="%i s" % seconds, font="Arial 30")
        label.place(x=posx, y=posy)
        label.after(1000, self.refresh_label, label, seconds, ball)

    def refresh_label(self, label, seconds, ball):
        seconds -= 1
        label.configure(text="%i s" % seconds)
        if seconds >= 0:
            label.after(1000, self.refresh_label, label, seconds, ball)
        elif seconds < 0:
            label.destroy()
            self.canvas.delete(ball)

class Ball:
    def __init__(self, master):
        master.title("Ball")
        master.geometry("1200x1200")
        #master.state('zoomed')
        self.master = master
        self.draw = Draw(master)

if __name__ == "__main__":
    master = tk.Tk() 
    pyBall = Ball(master)
    master.mainloop()