Ну во-первых, цикл у вас запускается не в отдельном потоке, а в том же потоке, что и окно. Это замечательно видно по тому, что окно фризится, пока цикл работает (не двигается, не ресайзится). То, что вы унаследовались от Thread еще не означает, что все, что вы запустите, будет работать в отдельном потоке. Пока у вас все в один поток идет. Оттуда, к слову, и ошибка - метод start() может быть вызван только один раз на один поток.
Простейший способ решить вашу задачу таков:
from tkinter import *
import time
import threading
class But_print():
def __init__(self):
self.but = Button(root)
self.but["text"] = "to count"
self.but.bind("<Button-1>", self.printer)
self.but.pack()
def thread(func):
'''
Это простейший декоратор. В него мы будем заворачивать
функции. Любая функция, завернутая этим декоратором,
будет выполнена в отдельном потоке.
'''
def wrapper(*args, **kwargs):
current_thread = threading.Thread(
target=func, args=args, kwargs=kwargs)
current_thread.start()
return wrapper
@thread # собственно, применяем декоратор
def printer(self, event):
for i in range(10):
print(10 - i - 1, "second")
time.sleep(1)
root = Tk()
obj = But_print()
root.mainloop()