Python通过线程tkinter进行通信

时间:2014-03-03 12:40:39

标签: python python-3.x tkinter

我正在创建一个基于文本的游戏,并且想要计算它运行了多少秒,这是我第一次使用tkinter,所以我不能完全确定我是否正确地完成了这一切。当我尝试使用counter()函数更新upt_label['text']upt_table时,我遇到了以下问题。

这是使用python 3.3,我需要引用什么才能在counter()中更改该变量?

from tkinter import *
import time
from threading import Thread

global upt_label

class OutBox(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent, background="black")

        self.parent = parent

        self.initUI()

    def initUI(self):
        self.parent.title("Text Adventure!")
        self.pack(fill=BOTH, expand=1)
        tpp_label = Label(self, text="Text Adventure!", fg="white", background="black", anchor="center", font=("Arial", 18))
        tpp_label.pack()
        upt_label = Label(self, text = "Uptime: 0", fg="white", background="black", anchor="center", font=("Arial", 12))
        upt_label.pack()

def main():
    root = Tk()
    root.geometry("560x720")
    app = OutBox(root)
    root.mainloop()

def counter():
    uptime = 0
    while True:
        upt_label['text'] = 'Uptime: %s' % uptime
        time.sleep(1)
        uptime = uptime + 1

gui_thread = Thread(target = main, args = ())
gui_thread.start()

upt_thread = Thread(target = counter, args = ())
upt_thread.start()

1 个答案:

答案 0 :(得分:3)

你遇到的部分问题是无法保证gui线程会在你的计数器线程运行之前初始化。要解决问题,您无法从创建它们的线程以外的任何线程安全地访问tkinter小部件。因此,即使您解决了启动顺序问题,您仍然需要解决其他问题。

好消息是,你不需要线程来解决这个问题。事实上,线程使这个问题更难。

如果您想每秒运行一次,请使用after来调用函数,然后让该函数使用after来安排自己在一秒钟内再次运行。

这是一个粗略的例子:

   def counter():
        global uptime
        uptime += 1
        upt_label['text'] = 'Uptime: %s' % uptime
        root.after(1000, counter)

注意这个函数如何更新标签,然后安排自己在一秒钟后再次调用。这可能有一点不准确,因为它不能保证在一秒之后精确运行。更准确的解决方案是节省程序启动的时间,然后获取当前时间并进行一些数学计算。这将使您在长期运行的程序中更准确地表示。