Встала задача написания небольшой графической оболочки для программы с минимальным интерфейсом (одна кнопка и одно поле вывода). Много нам не надо, поэтому решил обойтись идущей вместе с python’ом в поставке библиотекой TkInter. И тут столкнулся с небольшой проблемой – при нажатии кнопки запускаются довольно долгие и объёмные вычисления, из-за которых виснет весь интерфейс программы.
Решений у этого вопроса несколько.
1. Запускать эти вычисления в отдельном потоке, что меня вполне устроило:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | # -*- coding: utf-8 -*- import threading import time from Tkinter import * class AppGUI(object): def __init__(self): self.tk = Tk() frame = Frame(self.tk) frame.pack() Button(frame, text="Compute", command=self.computeWithGUIAntifreeze).pack() def run(self): self.tk.mainloop() def computeWithGUIAntifreeze(self): """Метод-прокладка для запуска в новом потоке вычислений""" threading.Thread(target=self.compute).start() def compute(self): """"Тут как раз и происходят длительные вычисления"""" time.sleep(15) gui = AppGUI() gui.run() |
2. Использовать время от времени методы:
- Tk.update();
- Tk.update_idletasks() – только обновляет окна, но не вызывает обработку событий, сгенерированных пользователем, в отличие от Tk.update();
Использовать эти методы стоит с осторожностью, дабы не возникло неприятных ситуаций (подробнее в документации). Таково предостережение официальной документации.
Почему если создавать окно ткинтера не через класс, появляется 2-е окно и вся программа подвисает?Потоки не работают(
Вероятно, вы что-то делаете не так, по сути никакой разницы нет: через класс что-то делать или нет. Ну или как вариант, за 4 года пример устарел и теперь в Tkinter это делается как-то иначе (впрочем, в этом я сомневаюсь).