Как в tkinter сделать вывод такой же как в консоли?

Вот для примера простой код:

import time

for i in range(10):
    print('abc')
    time.sleep(1)

Пытаюсь сделать то же самое, но в tkinter и по нажатию кнопки:

import time
import tkinter

def c():
    for i in range(10):
        t.insert(tkinter.END, 'abc\n')
        time.sleep(1)

root = tkinter.Tk()

t = tkinter.Text()
t.pack()

btn = tkinter.Button(text = 'Start', command = c)
btn.pack()

root.mainloop()

Первый код работает нормально. В консоль выводится последовательно 10 раз "abc" с интервалом в 1 секунду. А второй код работает немного по-другому. После нажатия кнопки питон думает 10 секунд, а затем выводит "abc" сразу 10 раз. Есть ли какой-то способ сделать в tkinter вывод аналогичный консольному?

UPD. С подсказкой от Amgarak сделал так:

import time
import tkinter

def c():
    for i in range(10):
        t.insert(tkinter.END, 'abc\n')
        root.update()
        time.sleep(1)

root = tkinter.Tk()

t = tkinter.Text()
t.pack()

btn = tkinter.Button(text = 'Start', command = c)
btn.pack()

root.mainloop()

Ответы (1 шт):

Автор решения: Amgarak

time.sleep(1) блокирует поток в том числе и цикл root.mainloop(), в следствии чего обновление интерфейса не происходит, и текст выводится в конце сразу за один раз.

Как вариант, обновлять интерфейс асинхронно или в отдельном потоке крутить цикл:

1)

import tkinter as tk

def c(i=0):
    if i < 10:
        t.insert(tk.END, 'abc\n')
        root.after(1000, c, i+1)  

root = tk.Tk()

t = tk.Text(root)
t.pack()

btn = tk.Button(root, text='Start', command=c)
btn.pack()

root.mainloop()
import time
import tkinter as tk
import threading

def c():
    def run():
        for i in range(10):
            t.insert(tk.END, 'abc\n')
            time.sleep(1)
            
    threading.Thread(target=run).start()

root = tk.Tk()

t = tk.Text(root)
t.pack()

btn = tk.Button(root, text='Start', command=c)
btn.pack()

root.mainloop()
→ Ссылка