Python - tkinter画布中的倒计时器

时间:2013-07-09 00:26:26

标签: python canvas timer tkinter

您好我想在子程序中创建一个倒数计时器,然后在画布上显示。我不完全确定从哪里开始我已经对它进行了一些研究,并且能够使用time.sleep(x)函数制作一个但是该方法会冻结整个程序,这不是我所追求的。我还在这里查看了关于计时器的其他问题并尝试将它们合并到我的程序中,但我还没有取得任何成功。

TLDR;我想创建一个倒计时器,从60秒开始倒计时并显示在画布上,然后在计时器达到0时让它做一些事情。

有人能指出我正确的方向吗?

提前致谢。

编辑:根据提供的建议,我试图将它们放入程序中而没有太多运气。

不确定此代码中是否存在重大错误,或者只是一个简单的错误。 我运行它时得到的错误在代码下面。

这是我想要定时器的代码的一部分:

def main(): #First thing that loads when the program is executed.
   global window
   global tkinter
   global canvas
   global cdtimer
   window = Tk()
   cdtimer = 60
   window.title("JailBreak Bob")

   canvas = Canvas(width = 960, height = 540, bg = "white")
   photo = PhotoImage(file="main.gif")
   canvas.bind("<Button-1>", buttonclick_mainscreen)
   canvas.pack(expand = YES, fill = BOTH)
   canvas.create_image(1, 1, image = photo, anchor = NW)
   window.mainloop()

def buttonclick_mainscreen(event):
   pressed = ""

   if event.x >18 and event.x <365 and event.y > 359 and event.y < 417 : pressed = 1 
   if event.x >18 and event.x <365 and event.y > 421 and event.y < 473 : pressed = 2 
   if event.x >18 and event.x <365 and event.y > 477 and event.y < 517 : pressed = 3 

   if pressed == 1 :
     gamescreen()
   if pressed == 2 :
     helpscreen()
   if pressed == 3 :
     window.destroy()

def gamescreen():
  photo = PhotoImage(file="gamescreen.gif")
  canvas.bind("<Button-1>", buttonclick_gamescreen)
  canvas.pack(expand = YES, fill = BOTH)
  canvas.create_image(1, 1, image = photo, anchor = NW)
  game1 = PhotoImage(file="1.gif")
  canvas.create_image(30, 65, image = game1, anchor = NW)
  e1 = Entry(canvas, width = 11)
  e2 = Entry(canvas, width = 11) 
  canvas.create_window(390, 501, window=e1, anchor = NW)
  canvas.create_window(551, 501, window=e2, anchor = NW)
  canvas.after(1, gamescreen)
  window.mainloop()

def cdtimer():
  canvas.delete(ALL)
  global cdtimer
  cdtimer -= 1
  canvas.create_text(510, 6, text=cdtimer, font="Ubuntu 29 bold", anchor = NW) 
  if cdtimer == 0:
    scorescreen()
  else:
    canvas.after(1000, gamescreen)

main()

错误MSG:

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.2/tkinter/__init__.py", line 1402, in __call__
    return self.func(*args)
  File "/usr/lib/python3.2/tkinter/__init__.py", line 490, in callit
    func(*args)
  File "/home/ppppwn3d/workspace/Python/JailBreakBob/JailBreakBob.py", line 50, in     gamescreen
    e1 = Entry(canvas, width = 11)
  File "/usr/lib/python3.2/tkinter/__init__.py", line 2372, in __init__
    Widget.__init__(self, master, 'entry', cnf, kw)
  File "/usr/lib/python3.2/tkinter/__init__.py", line 1952, in __init__
    cnf = _cnfmerge((cnf, kw))
  File "/usr/lib/python3.2/tkinter/__init__.py", line 71, in _cnfmerge
    if isinstance(cnfs, dict):
RuntimeError: maximum recursion depth exceeded while calling a Python object

3 个答案:

答案 0 :(得分:2)

您想使用after方法。逻辑是这样的:

def update_clock(self):
    self.counter -= 1
    if self.counter == 0 :
        do_something()
    else:
        self.after(1000, self.update_clock)

以上将从柜台中扣除一个。如果计数器为零,它会做一些特殊的事情。否则,它会安排自己在一秒钟内再次运行。

答案 1 :(得分:2)

这是奥克利回答的扩展。它演示了如何在画布中显示时间以及开始整个过程​​:

from tkinter import *
root = Tk()
canvas = Canvas(root)
canvas.pack()
time = 60
def tick():
    # You have to clear the canvas each time the clock updates 
    # (otherwise it writes on top of the old time).  Since the
    # time is the only thing in the canvas, delete(ALL) works
    # perfectly (if it wasn't however, you can delete the id
    # that goes with the clock).
    canvas.delete(ALL)
    # I have to declare time as a global because I'm not using
    # a class (otherwise, I could do something like self.time -= 1)
    global time
    time -= 1
    # You can place the time wherever in the canvas
    # (I chose 10,10 for the example)
    canvas.create_text(10, 10, text=time)
    if time == 0:
        do_something()
    else:
        canvas.after(1000, tick)
canvas.after(1, tick)
root.mainloop()

脚本从60秒开始倒计时(显示剩余时间),当它达到0时,它会调用do_something。

答案 2 :(得分:-1)

您可能想尝试线程化?

import thread
import time

def myFunct():
    sec = 60
    n = 1
    for i in range(sec/n):
        updateClock()
        time.sleep(n)
    finalFunct()

thread.start_new_thread(myFunct, ())

只需将sec更改为初始金额(以秒为单位),将n更改为您希望更新的时间间隔(以秒为单位)。