2014-11-24 67 views
0

如何使定时器在Canvas中更新?Tkinter GUI秒表/定时器

create.text(position, **options)默认位置,可以用anchor=tk.CENTER理应覆盖,但我得到一个:

NameError: name 'tk' is not defined

,如果我尝试添加anchor选项。

import time 
from Tkinter import * 

run = True; s=0; m=0; h=0 

def Run(): 
    global run, s, m, h 
    while run == True: 
     time.sleep(1) 
     s+=1 
     if s == 59: 
      m+=1; s=-1 
     elif m == 59: 
      h+=1; m=-1 

master = Tk() 
w = Canvas(master, width=1500, height=800) 
w.pack() 

x.create_text(
    [750, 400], anchor=tk.CENTER, text="%s:%s:%s" % (s, m, h), font=("Consolas", 400) 
    ) 

mainloop() 

Run() 

如果我mainloop()画布没有启动之前把Run()。在mainloop()Run()未启动后。

mainloop(Run())Run()Canvas之前开始。

+0

无限'while'循环使Tkinter锁定。考虑使用'Tk.after'来代替。 – Kevin 2014-11-24 19:30:03

+1

另外,如果你需要回答两个单独的问题,“为什么我会得到一个NameError?”,这可能是值得的。和“我如何定期更新计时器?” – Kevin 2014-11-24 19:31:45

回答

3

这条线:

from Tkinter import * 

将所有从Tkinter的库的名字进入全球namspace。所以,你可以直接访问它们:

x.create_text(
    ..., anchor=CENTER, ... 
    ) 

你会只做tk.CENTER了您导入Tkinter的,如:

import Tkinter as tk 

我必须说的是一个更好的办法。通过做from ... import *来混淆全局命名空间是一种糟糕的做法。记住:

"Namespaces are one honking great idea -- let's do more of those!"


关于你问题的第二部分,你不能在同一个线程中Tkinter的事件循环使用while True:time.sleep运行在做任何一项都将阻止Tkinter的。循环并导致您的程序冻结。

相反,你可以使用Tk.after在后台执行Run

from Tkinter import * 

run = True; s=0; m=0; h=0 

def Run(): 
    global run, s, m, h 

    # Delete old text 
    w.delete('all') 
    # Add new text 
    w.create_text(
     [750, 400], anchor=CENTER, text="%s:%s:%s" % (s, m, h), font=("Consolas", 400) 
     ) 

    s+=1 
    if s == 59: 
     m+=1; s=-1 
    elif m == 59: 
     h+=1; m=-1 

    # After 1 second, call Run again (start an infinite recursive loop) 
    master.after(1000, Run) 

master = Tk() 
w = Canvas(master, width=1500, height=800) 
w.pack() 

master.after(1, Run) # after 1 millisecond, start Run 
mainloop() 

而且,我搬到调用Canvas.create_textRun函数中,使其与中Run每次调用更新。请注意,在添加新文本之前,您需要先拨Canvas.delete,以便删除任何旧文本。