【问题标题】:Print letter by letter using Tkinter使用 Tkinter 逐个字母打印
【发布时间】:2018-01-27 13:36:31
【问题描述】:

有没有办法在 Python 3.4.1 中使用 Tkinter 逐字打印(在帧更新之间重绘)?

这在普通的空闲窗口中使用这段代码是可行的:

import time
string = "hello world"
for char in string:
    print(char, end='')
    time.sleep(.25)

但我不能在 GUI Tkinter 窗口中执行此操作。在我看来,我可以在 tkinter 窗口上显示一个标签,从一个字符串中添加一个字母,然后等待一段时间再添加另一个字母(大约 0.25 秒),与上面的代码相同。 有什么解决办法吗?

例如:

要显示的字符串 = 'abc'

第一帧:'a'

第二帧:'ab'

第三帧:'abc'

提前致谢!

【问题讨论】:

  • 逐帧打印?比如,在字母之间重绘。
  • 你可以这样做,是的,但是你想怎么做呢?
  • 请出示您的无效代码。
  • 您的第一步需要完成 tkinter 教程。一旦您了解了基础知识,请尝试编写一个在您需要时执行的程序。如果它不起作用,请尝试研究原因。只有在你做完这一切之后,你才能回到这里问一个问题。见How much research effort is expected of Stack Overflow users?
  • 参见tkintertag info获取更多资源,例如教程。

标签: python text tkinter


【解决方案1】:

你没有具体说明,所以我猜你会喜欢这样的:

import time
import tkinter as tk


def printString(string):
    for char in string:
        Label.configure(text=Label.cget('text') + char)
        Label.update()
        time.sleep(.25)

root = tk.Tk()
text = "Hello world!"
Label = tk.Label(root)
Label.pack()
printString(text)
root.mainloop()

更新:

原理相同,但对于 canvas

import time
import tkinter as tk


def printString(item, string):
    if item:
        for char in string:
            idx = c.index(item, tk.END)
            c.insert(item, idx, char)
            c.update()
            time.sleep(.25)


root = tk.Tk()
text = "Hello world!"
c = tk.Canvas(root)
c_txt = c.create_text(50,50)
c.pack()
c.update()
printString(c_txt, text)

root.mainloop()

【讨论】:

  • Tkinter 回调 Traceback 中的异常(最近一次调用最后一次):调用中的文件“C:\Python34\lib\tkinter_init_.py”,第 1487 行 return self.func(*args) File "C:\Python34\World Defense System 2.py",第 9 行,在 printString Label.configure(text=Label.cget('text') + char) 文件中“C:\Python34\lib\tkinter_init_.py”,第 1272 行,在 cget return self.tk.call(self._w, 'cget', '-' + key) _tkinter.TclError : 无效的命令名称“.36117616”
  • 有没有办法在不使用按钮的情况下激活 printString() 命令?
  • @hungnguyen 我已经对其进行了编辑,所以它一运行就开始播放。这更像你的意图吗?
  • 那么,这行:Label.configure(text=Label.cget('text') + char),意思是label每次运行都会添加一个新的字母?
  • 你能在画布上做这个吗?
【解决方案2】:

您可以使用after 定期调用方法来更新GUI。 time.sleep 像阻止 GUI 运行的主线程一样容易使用。


您可以定期替换label单个字符文本字符串中的下一个字母

 try:
    import tkinter as tk
except:
    import Tkinter as tk


def update_label_letter():
    global label
    label['text'] = label.string[label.current_char_index]
    label.current_char_index += 1
    label.current_char_index %= len(label.string)
    label.after(250, update_label_letter)


if __name__ == '__main__':
    root = tk.Tk()
    label = tk.Label(root)
    label.string = "Hello World!"
    label.current_char_index = 0
    root.after(250, update_label_letter)
    label.pack()
    root.mainloop()

一种方法是定期追加单个label的字母

垂直:

try:
    import tkinter as tk
except:
    import Tkinter as tk


def update_label_letters():
    global label
    _no_of_space_replacements = label['text'].count('\n')
    _last_char_index = len(label['text']) - _no_of_space_replacements
    if _last_char_index < len(label.string):
        label['text'] += label.string[_last_char_index].replace(" ", " \n")
    else:
        label['text'] = ""
    label.after(250, update_label_letters)


if __name__ == '__main__':
    root = tk.Tk()
    label = tk.Label(root, wraplength=1)
    label.string = "Hello World!"
    root.after(250, update_label_letters)
    label.pack()
    root.mainloop()

水平:

try:
    import tkinter as tk
except:
    import Tkinter as tk


def update_label_letters():
    global label
    _last_char_index = len(label['text'])
    if _last_char_index < len(label.string):
        label['text'] += label.string[_last_char_index]
    else:
        label['text'] = ""
    label.after(250, update_label_letters)


if __name__ == '__main__':
    root = tk.Tk()
    label = tk.Label(root)
    label.string = "Hello World!"
    root.after(250, update_label_letters)
    label.pack()
    root.mainloop()

另一种方法是定期写字母清空但显示letter_labels

垂直:

try:
    import tkinter as tk
except:
    import Tkinter as tk


def update_label_letters():
    global current_char_index, my_string, letter_labels
    if current_char_index < len(my_string):
        _current_char = my_string[current_char_index]
        letter_labels[current_char_index]['text'] = _current_char
        letter_labels[current_char_index].after(250, update_label_letters)
        current_char_index += 1


if __name__ == '__main__':
    root = tk.Tk()

    my_string = "Hello World!"
    letter_labels = list()
    for index, value in enumerate(my_string):
        letter_labels.append(tk.Label(root))
        letter_labels[index].pack()
    current_char_index = 0
    root.after(250, update_label_letters)
    root.mainloop()

水平:

try:
    import tkinter as tk
except:
    import Tkinter as tk


def update_label_letters():
    global current_char_index, my_string, letter_labels
    if current_char_index < len(my_string):
        _current_char = my_string[current_char_index]
        letter_labels[current_char_index]['text'] = _current_char
        letter_labels[current_char_index].after(250, update_label_letters)
        current_char_index += 1


if __name__ == '__main__':
    root = tk.Tk()

    my_string = "Hello World!"
    letter_labels = list()
    for index, value in enumerate(my_string):
        letter_labels.append(tk.Label(root))
        letter_labels[index].pack(side='left')
    current_char_index = 0
    root.after(250, update_label_letters)
    root.mainloop()

另一种方法是定期显示letter_labels

垂直:

try:
    import tkinter as tk
except:
    import Tkinter as tk


def show_label():
    global current_char_index, my_string, letter_labels
    if current_char_index < len(my_string):
        letter_labels[current_char_index].pack()
        letter_labels[current_char_index].after(250, show_label)
        current_char_index += 1


if __name__ == '__main__':
    root = tk.Tk()

    my_string = "Hello World!"
    letter_labels = list()
    for _char in my_string:
        letter_labels.append(tk.Label(root, text=_char))
    current_char_index = 0
    root.after(250, show_label)
    root.mainloop()

水平:

try:
    import tkinter as tk
except:
    import Tkinter as tk


def show_label():
    global current_char_index, my_string, letter_labels
    if current_char_index < len(my_string):
        letter_labels[current_char_index].pack(side='left')
        letter_labels[current_char_index].after(250, show_label)
        current_char_index += 1


if __name__ == '__main__':
    root = tk.Tk()

    my_string = "Hello World!"
    letter_labels = list()
    for _char in my_string:
        letter_labels.append(tk.Label(root, text=_char))
    current_char_index = 0
    root.after(250, show_label)
    root.mainloop()

【讨论】:

  • 它有效,但它是垂直的,但我想要它水平?
  • @hungnguyen 对不起。要是我能猜到就好了。
  • 成功了!但是有没有办法打印字符串之间没有空格?
  • @hungnguyen 我不确定你的意思,但前两个解决方案的空格最少。
猜你喜欢
  • 1970-01-01
  • 2021-04-20
  • 1970-01-01
  • 2020-12-12
  • 1970-01-01
  • 1970-01-01
  • 2021-09-18
  • 2019-03-19
  • 1970-01-01
相关资源
最近更新 更多