【问题标题】:tkinter after() function won't call itself to create looptkinter after() 函数不会调用自身来创建循环
【发布时间】:2018-02-15 05:53:19
【问题描述】:

所以,我正在尝试使用 start 在 tkinter 程序中创建一个时钟。根据文档,第一个 after 应该调用一个函数,然后你应该把 after 函数放在被调用的函数中,让它一遍又一遍地运行。但是,当我这样做时,第一个 after 会很好地调用我的函数,然后在我的函数中调用 after that 会告诉我该函数未定义。我不明白为什么会发生这种情况或如何解决它。

对 after 的第一次调用在底部,它调用 updateTime() 函数。正是在该函数中,它应该在 1 秒延迟后调用自身,但会出现错误。

另外,我是 python 和 tkinter 的新手,所以如果这是错误的方法,请告诉我。 after 函数似乎是最好的方法。

from Tkinter import *
import time
#from relayControl import switchOnOff

#Pin numbers:
#Light:  2
#Fan:    3

class Main:

    def exit():
        quit()

    def lightSwitch():
        print("Light on")
        #switchOnOff(2)

    def fanSwitch():
        print("Fan on")
        #switchOnOff(3)

    def updateTime(timeLabel, root):
        timeLabel.config(text=time.strftime("%H:%M:%s", time.localtime()))
        root.after(100, updateTime(timeLabel, root))


    root = Tk()
    root.configure(background="black")
    root.columnconfigure(1, weight=1)
    root.columnconfigure(2, weight=1)
    root.columnconfigure(3, weight=1)
    root.rowconfigure(1, weight=1)
    root.rowconfigure(2, weight=1)
    root.rowconfigure(3, weight=1)

    # ***Time(center)***
    timeLabel = Label(root, text=time.strftime("%H:%M:%s", time.localtime()), bg="black", fg="red")
    timeLabel.grid(row=2, column=2)

    # ***Alarm(top left)***
    alarmLabel = Label(root, text="Alarm Time", bg="black", fg="red")
    alarmLabel.grid(row=1, column=1)

    # ***Exit(bottom right)
    exitButton = Button(root, text="Exit", bg="red", highlightbackground="red", command=exit)
    exitButton.grid(row=3, column=3)

    # ***Frequently used switches(top right)***
    buttonFrame = Frame(root, bg="black")
    buttonFrame.grid(row=1, column=3)

    lightSwitch = Button(buttonFrame, text="Light", bg="red", highlightbackground="red", command=lightSwitch)
    lightSwitch.pack()

    fanSwitch = Button(buttonFrame, text="Fan", bg="red", highlightbackground="red", command=fanSwitch)
    fanSwitch.pack()

    root.after(100, updateTime(timeLabel, root))
    root.mainloop() 

错误:

Traceback (most recent call last):
  File "/home/leemorgan/projects/python/automatedHome/main.py", line 9, in <module>
    class Main:
  File "/home/leemorgan/projects/python/automatedHome/main.py", line 60, in Main
    root.after(100, updateTime(timeLabel, root))
  File "/home/leemorgan/projects/python/automatedHome/main.py", line 24, in updateTime
    root.after(100, updateTime(timeLabel, root))
NameError: global name 'updateTime' is not defined

【问题讨论】:

  • 必须是self.updateTime
  • 好的,这似乎可行,但我遇到了另一个问题。为此,我必须将 self 添加到函数参数中。那么当我调用这个参数时,我应该为它传递什么?我传入了两个参数,但现在需要 3 个。
  • 您似乎对如何创建类方法一无所知。 每个类方法必须以self为第一个参数。
  • 是的,对不起。来自 Java 和 C++ 等语言,所以这对我来说很奇怪。从我查找的示例中,它们似乎将 self 作为第一个参数,您不需要将其传入。好吧,我将 self 添加到所有方法中,明白了。但是,它仍然告诉我必须传入 3 个参数而不是两个。
  • 其实你有一个更大的问题。向root.after传递参数时,必须是函数名,不能是函数调用。

标签: python tkinter


【解决方案1】:

我认为你需要一个lambda 命令,所以试试:

root.after (100, lambda timeLabel = timeLabel, root = root: Main.updateTime (timeLabel, root))

编辑: 使用 Brian Oakley 的评论(一种更好的方法):

root.after (100, Main.updateTime, timeLabel, root)

【讨论】:

  • 你可以使用lambda,但你不需要。 IMO 它使代码更难阅读。您可以直接在after 内传递参数:root.after(100, Main.updateTIme, timeLabel, root)
  • 酷!我没有意识到这一点!
猜你喜欢
  • 1970-01-01
  • 2011-03-09
  • 1970-01-01
  • 2018-09-02
  • 1970-01-01
  • 1970-01-01
  • 2020-11-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多