Tkinter не является потокобезопасным - вы не можете манипулировать виджетами ни в одном потоке, кроме основного, иначе вы получите неопределенные результаты.
Вам не нужны темы для этого. Ваш код добавляет бесконечный цикл, но в приложении уже есть бесконечный цикл (цикл обработки событий), которым вы можете воспользоваться.
Если вы хотите переместить какой-либо элемент, создайте функцию, которая делает две вещи. Во-первых, он делает все, что вы хотите, например, перемещает элемент. Во-вторых, он использует стандартный метод after
для повторного вызова себя за короткое время (например, полсекунды или 500 мс). Таким образом, вы позволяете своему циклу событий управлять анимацией, вам не нужны потоки, и ваш пользовательский интерфейс остается отзывчивым.
Вот пример. Я сомневаюсь, что это именно то, что вы хотите, потому что я не уверен, что именно вы хотите.
import Tkinter as tk
import random
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
self._running = False
self._relx = None
tk.Tk.__init__(self, *args, **kwargs)
self.pack_propagate(False)
self.configure(width=400, height=400)
self.label = tk.Label(self, text="hello, world", background="red")
self.button = tk.Button(self, text="Start", command=self.toggle)
self.button.pack(side="top")
def toggle(self):
'''toggle animation on or off'''
self._running = not self._running
if self._running:
self.button.configure(text="Stop")
self.moveit()
else:
self.button.configure(text="Start")
def moveit(self):
'''Animate the label'''
if not self._running:
# animation has been stopped
# hide the label from view.
self.label.place_forget()
if self._running:
if not self.label.winfo_viewable():
# not visible; establish future locations
self._relx = [.5, .4, .3, .2, .1, 0]
relx = self._relx.pop(0)
self._relx.append(relx)
self.label.place(relx=relx, rely=0.7)
self.after(1000, self.moveit)
if __name__ == "__main__":
app = SampleApp()
app.mainloop()