Python tkinter在循环中更改stringvar,但不影响窗口

Python tkinter在循环中更改stringvar,但不影响窗口,python,tkinter,Python,Tkinter,当我按下tk中的按钮时,我想每秒更改一次标签: # --coding:utf-8 ----- from Tkinter import * import time import random def test(a): begin =time.time() end =time.time() while True: ran = random.random() after = time.time() if(after-begin

当我按下tk中的按钮时,我想每秒更改一次标签:

# --coding:utf-8 -----
from Tkinter import *
import time
import random

def test(a):
    begin =time.time()
    end =time.time()
    while True:
        ran = random.random()
        after = time.time()
        if(after-begin >1):
            a.set(str(ran))
            print a.get()
            begin =after
        if(after-end>10):
            a.set('over')
            break


t = Tk()
a = StringVar()
a.set('0')
b = Label(t,textvariable = a)
b.pack()
Button(t,text ='test',command = lambda x=a:test(a)).pack()


t.mainloop()
我的控制台输出是正确的,但对windows没有影响。为什么?

您可以在单独的线程中启动test()函数,如下所示:

# --coding:utf-8 -----
from Tkinter import *
import time
import random
import threading

def startThread(a):
    threading.Thread(target=test, args=(a,)).start()

def test(a):
    begin =time.time()
    end =time.time()
    while True:
        ran = random.random()
        after = time.time()
        if(after-begin >1):
            a.set(str(ran))
            print a.get()
            begin =after
        if(after-end>10):
            a.set('over')
            break


t = Tk()
a = StringVar()
a.set('0')
b = Label(t,textvariable = a)
b.pack()
Button(t,text ='test',command = lambda x=a:startThread(a)).pack()


t.mainloop()

然而,即使关闭窗口,线程也要到10秒结束时才会结束。您需要为
while
循环找到一些代码,以检查应用程序是否仍在运行。

创建必须在给定时间段内执行的行为是一个常见问题;你可以通过一个专门的
服务员
课程来解决这个问题;这避免了使用
tkinter
不支持的线程

下面的示例打开一个带有标签和按钮的窗口。按下按钮后,标签将在10秒内每秒钟更新一次,然后停止。
在10秒内再次按下按钮无效;之后,它会重新启动进程10秒以上

import Tkinter as tk    # tkinter if python >= 3 

import time
import random


class Waiter(object):

    def __init__(self, waiting_time):
        """
        :param waiting_time: int, in seconds
        """
        self.waiting_time = waiting_time
        self.expiring_time = time.time() + self.waiting_time
        self.waiting = True
        # print('waiter started')

    def stop(self):
        # print('waiter stopping')
        self.expiring_time = None
        self.waiting = False

    def is_waiting(self):
        """returns True while waiting, false otherwise"""
        if time.time() > self.expiring_time:
            self.stop()
        return self.waiting


def atest():
    global waiter
    if waiter is None:
        waiter = Waiter(10)
        _atest()


def _atest():
    """ equivalent to: 
    while the waiter is waiting, 
    change the label every second),
    then destroy the waiter
    """
    global waiter
    if waiter.is_waiting():
        a.set(random.random())
        # print(time.time())
        t.after(1000, _atest)
    else:
        waiter = None


if __name__ == '__main__':

    waiter = None
    t = tk.Tk()
    a = tk.StringVar()
    a.set('0')
    tk.Label(t, textvariable=a).pack()
    tk.Button(t, text='test', command=atest).pack()

    t.mainloop()
注: 您可以将
\u atest
作为
atest
的一个内部函数,但它可能更容易理解

使用
import Tkinter as tk
而不是从Tkinter import*
中使用
导入Tkinter as tk,可以防止名称空间混乱,并可以使代码更清晰。
您可能应该考虑使用Python 3。