【问题标题】:Is there a way to update label in real-time in tkinter?有没有办法在 tkinter 中实时更新标签?
【发布时间】:2020-09-30 14:26:34
【问题描述】:

在 Tkinter 的帮助下,我尝试一次打印一个单词(间隔 2 秒睡眠) 我尝试了以下代码,它没有按我想要的那样工作。 我的代码正在打印一个堆叠在一起的整个字符串。

在经过 n*len(words) 秒后。

我尝试一次只打印一个单词(间隔为 2 秒)

from tkinter import *
from time import sleep
root = Tk()
words = 'Hey there, This is python3'.split()
l = Label(root, text='')

for w in range(len(words)):
    sleep(2)
    l = Label(root,text = words[w])
    #l['text'] = words[w] # this is what I tried
    l.pack()
    root.mainloop()

我尝试了上面评论的声明,认为这可能会更新,但根本没有像我预期的那样工作。

【问题讨论】:

  • 这个网站上有很多类似的问题。
  • 使用after()config()?,如果您需要答案,请告诉我
  • @BryanOakley 是的,它们非常相似,但没有一个与我正在尝试的匹配。
  • @CoolCloud 我尝试了配置,它只显示第一个单词(即“嘿”)。没有更新到下一个单词。我也在尝试互联网上所有可能的解决方案。
  • 我已经添加了答案

标签: python python-3.x tkinter


【解决方案1】:

看看这个例子:

from tkinter import *

root = Tk()

words = 'Hey there, This is python3'.split()
l = Label(root) #creating empty label without text
l.pack()

w = 0 #index number
def call():
    global w
    if w <= len(words)-1: #if it is in the range of the list
        l.config(text=words[w]) #change the text to the corresponding index element
        w += 1 #increase index number
        root.after(2000,call) #repeat the function after 2 seconds
    else:
        print('Done') # if out of index range, then dont repeat
call() #call the function initially

root.mainloop() 

我已经对代码进行了注释以便更好地理解。

使用after()的方法会重复调用函数,可能会降低效率。因此,您也可以使用 threading 启动一个新线程,在 sleep() 时不会使 GUI 冻结:

from tkinter import *
from time import sleep
import threading #import the library

root = Tk()
words = 'Hey there, This is python3'.split()
l = Label(root) #empty label
l.pack() #pack()

def call():
    for w in words: #loop through the list
        l.config(text=w) #update label with each word over each iteration
        sleep(2) #sleep for 2 seconds

threading.Thread(target=call).start() #create a separate thread to not freeze the GUI

root.mainloop()

【讨论】:

  • 嗨酷云。我想知道您是否不知道 Stack Overflow 的目标是采用技术性、简洁的写作风格。考虑到这一点,您能否尽量避免添加感谢,并希望您的回答有所帮助?这些通常会由志愿编辑删除,如果不添加它们会为我们节省一些工作。
【解决方案2】:

使用线程的简单答案,因为 time.sleep(2) 将使整个 tkinter 在实际显示窗口之前等待几秒钟。

from tkinter import *
import time
from threading import Thread
root = Tk()

words = 'Hey there, This is python3'.split()
l = Label(root, text='')
l.pack()

def show_words():
    for word in words:
        time.sleep(2)
        l.configure(text=word)

thread = Thread(target = show_words)
thread.start()

root.mainloop()

【讨论】:

  • 线程会增加开销,而且很危险,因为 tkinter 不是线程安全的。
  • 你能详细说明一下吗?我知道 tkinter 是单线程的,但我认为创建另一个线程可以吗?
  • tkinter 有能力安排未来的功能。每隔几秒更新一个标签是微不足道的,不会带来线程的复杂性。
  • 如果 tkinter 将来调度一个函数,它将如何影响标签?如果该函数与标签有关,那么到那时线程已经死了,这有关系吗?
  • 未来计划的函数可以为所欲为,包括更新标签。
【解决方案3】:

您首先需要将 mainloop() 从 for 循环中取出,因为它只是发送命令以再次运行根目录,因此只打印第一个单词。我也使用了一个计时器和一个新屏幕(注意:你也可以在 root 上做同样的事情),我启动了计时器,并在当前时间的特定时间后发送了一个命令来运行 def。我希望帮助了你。

from tkinter import *
import threading
from time import sleep
root = Tk()
words = 'Hey there, This is python3'.split()
l = Label(root, text='')
print(words);
def newWindow():
         global newScreen
         newScreen=Toplevel()
         newScreen.title("Rahul Screen")
         newScreen.geometry("300x300+15+15")
         newScreen.resizable(0,0)
         l=Label(newScreen,text='')
         for w in range(len(words)):
             print(w);
             sleep(2)
             l = Label(newScreen,text = words[w])
             l.pack()
start_time = threading.Timer(2,newWindow)
start_time.start()
root.mainloop()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-20
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多