tkinter:模拟时钟刷新 - """功能工作?

时间:2015-05-14 20:26:20

标签: python tkinter clock

最近,我是python的初学者,我在Tkinter上编程了一个模拟时钟,它可以每秒显示一次。但是这个时钟使用while 1无限循环来刷新时间,这完全阻止了程序的其余部分。因为我想在另一个程序中使用它,作为并行函数,我不得不重新编程刷新方法。

我发现after()函数可以(我认为)帮助我,但我得到RuntimeError: maximum recursion depth exceeded in comparison并且我不明白为什么。我的时钟绘图对于python来说太重了吗?我将代码放在这里,希望有人了解我的问题并帮助我。

(PS 1:我之前没有注意代码"原则功能"我不认为问题存在,但我仍然会发布它因为我完全不确定这部分是否经过调试。

PS 2:我真的很抱歉我的英语可能有问题,所以请告诉我你是否理解。)

#list of imported modules
from tkinter import *
from math import cos, sin
from time import gmtime, sleep

#defining of secondary functions

def drawcircle(Alpha,Beta,Rayon,Couleur,can): #draw a circle base on center coord radius and color
    x1,y1,x2,y2=Alpha-Rayon, Beta-Rayon, Alpha+Rayon, Beta+Rayon
    can.create_oval(x1,y1,x2,y2,fill=Couleur)

def drawPetAig(CoordA, CoordZ, Taille, Omega, can): #function to drawn the second hand of the clock
    Pi = 3.141592
    Omega = ((Omega/60)+1)*30
    can.create_line(CoordA + (Taille/3) * cos(Pi*(Omega/180)), CoordZ + (Taille/3) * sin(Pi*(Omega/180)), CoordA - (Taille/8) * cos(Pi*(Omega/180)), CoordZ - (Taille/8) * sin(Pi*(Omega/180)) )

def drawGrdAig(CoordA, CoordZ, Taille, Omega, can): #function to draw the minute hand, based on center coord and minutes.
    Pi = 3.141592
    Omega = (Omega-15)*6
    can.create_line(CoordA + (Taille/1.5) * cos(Pi*(Omega/180)), CoordZ + (Taille/1.5) * sin(Pi*(Omega/180)), CoordA - (Taille/6) * cos(Pi*(Omega/180)), CoordZ - (Taille/6) * sin(Pi*(Omega/180)))

def drawSecAig(CoordA, CoordZ, Taille, Omega, can): #function to draw the hour hand
    Pi = 3.141592
    Omega = (Omega-15) *6
    can.create_line(CoordA + (Taille/1.5) * cos(Pi*(Omega/180)), CoordZ + (Taille/1.5) * sin(Pi*(Omega/180)), CoordA - (Taille/6) * cos(Pi*(Omega/180)), CoordZ - (Taille/6) * sin(Pi*(Omega/180)), fill = "red")

def fondhorloge(CoordA, CoordZ, Taille, can1):  #function drawing the backgroud of the clock
    Pi = 3.141592
    drawcircle(CoordA, CoordZ, Taille + (Taille/10), "grey6",can1) #drawing the surrounding of the clock
    drawcircle(CoordA, CoordZ, Taille, "ivory3",can1)#backgroud
    drawcircle(CoordA, CoordZ, Taille/80, "grey6",can1)#central point/needle articulation
    can1.create_line(CoordA + (Taille - (Taille/15)), CoordZ, CoordA + (Taille - (Taille/5)), CoordZ) #drawing the N/S/E/W decorativ hour position
    can1.create_line(CoordA, CoordZ + (Taille - (Taille/15)), CoordA, CoordZ + (Taille - (Taille/5)))
    can1.create_line(CoordA - (Taille - (Taille/15)), CoordZ, CoordA - (Taille - (Taille/5)), CoordZ)
    can1.create_line(CoordA, CoordZ - (Taille - (Taille/15)), CoordA, CoordZ - (Taille - (Taille/5)))

    #here, this 4*2 line defined the position of the 8 intermediate line between the N/S/E/W decorativ line.
    can1.create_line(CoordA + (Taille/1.05) * cos(Pi*(30/180)), CoordZ + (Taille/1.05) * sin(Pi*(30/180)), CoordA + (Taille/1.20) * cos(Pi*(30/180)), CoordZ + (Taille/1.20) * sin(Pi*(30/180)))
    can1.create_line(CoordA + (Taille/1.05) * cos(Pi*(60/180)), CoordZ + (Taille/1.05) * sin(Pi*(60/180)), CoordA + (Taille/1.20) * cos(Pi*(60/180)), CoordZ + (Taille/1.20) * sin(Pi*(60/180)))

    can1.create_line(CoordA - (Taille/1.05) * cos(Pi*(30/180)), CoordZ - (Taille/1.05) * sin(Pi*(30/180)), CoordA - (Taille/1.20) * cos(Pi*(30/180)), CoordZ - (Taille/1.20) * sin(Pi*(30/180)))
    can1.create_line(CoordA - (Taille/1.05) * cos(Pi*(60/180)), CoordZ - (Taille/1.05) * sin(Pi*(60/180)), CoordA - (Taille/1.20) * cos(Pi*(60/180)), CoordZ - (Taille/1.20) * sin(Pi*(60/180)))

    can1.create_line(CoordA + (Taille/1.05) * cos(Pi*(30/180)), CoordZ - (Taille/1.05) * sin(Pi*(30/180)), CoordA + (Taille/1.20) * cos(Pi*(30/180)), CoordZ - (Taille/1.20) * sin(Pi*(30/180)))
    can1.create_line(CoordA + (Taille/1.05) * cos(Pi*(60/180)), CoordZ - (Taille/1.05) * sin(Pi*(60/180)), CoordA + (Taille/1.20) * cos(Pi*(60/180)), CoordZ - (Taille/1.20) * sin(Pi*(60/180)))

    can1.create_line(CoordA - (Taille/1.05) * cos(Pi*(30/180)), CoordZ + (Taille/1.05) * sin(Pi*(30/180)), CoordA - (Taille/1.20) * cos(Pi*(30/180)), CoordZ + (Taille/1.20) * sin(Pi*(30/180)))
    can1.create_line(CoordA - (Taille/1.05) * cos(Pi*(60/180)), CoordZ + (Taille/1.05) * sin(Pi*(60/180)), CoordA - (Taille/1.20) * cos(Pi*(60/180)), CoordZ + (Taille/1.20) * sin(Pi*(60/180)))

#PRINCIPLE FUNCTION (here the problem starts)

def HORLOGE1(Gamma, Pi, Epsylon):# draw a clock with the center position x/x = gamma/pi and the radius = epsylon

    fondhorloge(Gamma, Pi, Epsylon, can1)# extracting time value
    patate = gmtime()
    heure = patate[3] + 1  # "+1" is changing time from english time to french time :P
    minute = patate[4]
    seconde = patate[5]

    print(heure, minute, seconde) # a simple test to watch what the programm is doing (run it, and you'll see, that this test is done tausend time per second, that why I think the problem is here.)
    drawPetAig(Gamma, Pi, Epsylon, minute, can1)
    drawGrdAig(Gamma, Pi, Epsylon, minute, can1)
    drawSecAig(Gamma, Pi, Epsylon, seconde, can1)
    fen1.after(1000, HORLOGE1(250, 250, 200))

#execution of the main function

fen1 = Tk()
can1 = Canvas(fen1, bg="white", height=500, width=500)
can1.pack()

HORLOGE1(250, 250, 200)

fen1.mainloop()
fen1.destroy()

1 个答案:

答案 0 :(得分:4)

问题在于,在原则函数中,HORLOGE1()在尝试安排在指定的1秒延迟后再次调用它时立即调用自身。这发生在最后一行:

fen1.after(1000, HORLOGE1(250, 250, 200))

一种简单的方法可以防止这种情况,而是使用类似的东西:

fen1.after(1000, lambda: HORLOGE1(250, 250, 200))

这样做是使用lambda expression 创建匿名函数。创建的函数接受/不需要参数,它所做的就是在调用时调用HORLOGE1(250, 250, 200)该函数然后作为第二个参数传递给fen1.after()

值得注意的是,这样做而不是实际上在此过程中调用了HORLOGE1().after()的第二个参数应该几乎总是可调用的 - 比如函数或绑定方法 - 而不是调用它的结果,就像你正在做的那样。

进行更改后,您应该看到类似这样的东西,同时移动时钟指针:

screenshot of analog clock displayed in tkinter window