如何在 tkinter 中为每个分割屏幕添加计时器

Posted

技术标签:

【中文标题】如何在 tkinter 中为每个分割屏幕添加计时器【英文标题】:How to add timer to each divide screen in tkinter 【发布时间】:2020-01-08 14:54:50 【问题描述】:

我创建了一个窗口并将其拆分为 3 个不同的窗口。我想为每个屏幕添加一个时钟,它不依赖于其他时钟。 我的代码打开了 2 个窗口 - 一个是计时器,第二个是我拆分为 3 个窗口的窗口。

    from tkinter import *
import Tkinter as tk


class split_screen(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.label = tk.Label(self, text="", width=10,fg="black", bg ="red", font="david 18 bold underline")
        self.label.pack()
        self.remaining = 0
        self.countdown(1000)
        self.configure(background="black")


    def screen(self):
        root = Tk()
        root.geometry("650x700")
        root.configure(bg='black')
        root.title("test")
        left = Frame(root, borderwidth=200, relief="solid")
        right = Frame(root, borderwidth=20, relief="solid")
        box3 = Frame(right, borderwidth=2, relief="solid")
        box1 = Frame(left, borderwidth=2, relief="solid")
        box2 = Frame(left, borderwidth=2, relief="solid")

        label1 = Label(box3, text="winner's" + "\n\n\n" + "Player 1",fg= "black", bg = "red", font = "david 18 bold underline")
        label2 = Label(box1, text="Computer 1",fg = "black", bg = "red", font= "david 18 bold underline")
        label3 = Label(box2, text="Computer 2",fg = "black", bg = "red", font= "david 18 bold underline")

        left.pack(side="left", expand=True, fill="both")
        right.pack(side="right", expand=True, fill="both")

        box3.pack(expand=True, fill="both", padx=10, pady=10)
        box1.pack(expand=True, fill="both", padx=10, pady=10)
        box2.pack(expand=True, fill="both", padx=10, pady=10)

        label1.pack()
        label2.pack()
        label3.pack()


    def countdown(self, remaining = None):
        if remaining is not None:
            self.remaining = remaining

        if self.remaining <= 0:
            self.label.configure(text="time's up!")
        else:
            self.label.configure(text="%d" % self.remaining)
            self.remaining = self.remaining - 1
            self.after(1000, self.countdown)

if __name__ == "__main__":
    app = split_screen()
    app.screen()
    app.mainloop()

【问题讨论】:

您不应创建多个Tk 实例。任何基于该设计的解决方案都会有额外的问题。 @BryanOakley 所以我不能在不产生任何额外问题的情况下为每个分屏添加时钟? 不,我没有说时钟,我说的是“Tk 的实例”。您应该只有一个 Tk 实例,但您有两个实例。 @BryanOakley 好的。那你能指导我吗? 额外的窗口需要是Toplevel的实例。 【参考方案1】:

我做了多项更改: 正如 Bryan Oakley 所说,不要创建 Tk() 的多个实例。您也不需要两次导入 tkinter。

import tkinter as tk


class split_screen(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)

        self.geometry("650x700")
        self.configure(bg='black')
        self.title("test")
        left = tk.Frame(self, borderwidth=200, relief="solid")
        right = tk.Frame(self, borderwidth=20, relief="solid")
        box1 = tk.Frame(left, borderwidth=2, relief="solid")
        box2 = tk.Frame(left, borderwidth=2, relief="solid")
        box3 = tk.Frame(right, borderwidth=2, relief="solid")

        label1 = tk.Label(box3, text="winner's" + "\n\n\n" + "Player 1",fg= "black", bg = "red", font = "david 18 bold underline")
        label2 = tk.Label(box1, text="Computer 1",fg = "black", bg = "red", font= "david 18 bold underline")
        label3 = tk.Label(box2, text="Computer 2",fg = "black", bg = "red", font= "david 18 bold underline")

        clock1 = Clock(box1, 1000)
        clock2 = Clock(box2, 2000)
        clock3 = Clock(box3, 1300)

        left.pack(side="left", expand=True, fill="both")
        right.pack(side="right", expand=True, fill="both")

        box3.pack(expand=True, fill="both", padx=10, pady=10)
        box1.pack(expand=True, fill="both", padx=10, pady=10)
        box2.pack(expand=True, fill="both", padx=10, pady=10)

        label1.pack()
        label2.pack()
        label3.pack()


class Clock():
    def __init__(self, frame, count):
        self.frame = frame
        self.label = tk.Label(frame, text="", width=10,fg="black", bg ="red", font="david 18 bold underline")
        self.label.pack()
        self.remaining = 0
        self.countdown(count)
        frame.configure(background="black")

    def countdown(self, remaining = None):
        if remaining is not None:
            self.remaining = remaining

        if self.remaining <= 0:
            self.label.configure(text="time's up!")
        else:
            self.label.configure(text="%d" % self.remaining)
            self.remaining = self.remaining - 1
            self.frame.after(1000, self.countdown)

if __name__ == "__main__":
    app = split_screen()
    app.mainloop()

【讨论】:

【参考方案2】:

最简单的解决方案——可以说是最好的——是创建一个代表单个计时器的类。然后,您可以根据需要创建任意数量的实例。这正是类的用途:将某些行为封装在对象中。

由于您使用标签来显示时间,您可以让计时器类继承自Label,也可以在创建计时器时传入标签。

这是一个继承自 tk.Label 的示例:

import tkinter as tk

class TimerLabel(tk.Label):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.after_id = None
        self.remaining = None

    def countdown(self, seconds):
        if seconds <= 0:
            self.configure(text="Time's up!")
        else:
            self.configure(text=f"seconds")
            self.after_id = self.after(1000, self.countdown, seconds-1)

    def stop(self):
        if self.after_id:
            self.configure(text="cancelled")
            self.after_cancel(self.after_id)

使用上面的类定义,您可以根据需要创建任意数量的计时器小部件。这是一个创建三个的示例:

root = tk.Tk()

timer1 = TimerLabel(root, width=10)
timer2 = TimerLabel(root, width=10)
timer3 = TimerLabel(root, width=10)

timer1.pack(side="top", padx=20)
timer2.pack(side="top", padx=20)
timer3.pack(side="top", padx=20)

timer1.countdown(30)
timer2.countdown(20)
timer3.countdown(10)

root.mainloop()

【讨论】:

以上是关于如何在 tkinter 中为每个分割屏幕添加计时器的主要内容,如果未能解决你的问题,请参考以下文章

如何在 tkinter 中为多个按钮创建全局样式?

如何在 GraphQL 突变/解析器中为每个用户创建和停止唯一的计时器

在 XCODE 8 Swift 3 中为倒数计时器添加音调

如何在本机反应中为整个应用程序(如每个屏幕)在屏幕底部显示自定义视图

如何在Tkinter,Python 3中为方块提供随机方向

在recycleview时间轴中为每个视图添加drawable