Как запустить функцию в фоновом режиме tkinter
Я новичок в программировании GUI и хочу написать программу на Python с помощью tkinter. Все, что я хочу, это запустить простую функцию в фоновом режиме, на которую можно влиять через графический интерфейс.
Функция считает от 0 до бесконечности, пока не будет нажата кнопка. По крайней мере, я этого хочу. Но я понятия не имею, как я могу запустить эту функцию в фоновом режиме, потому что mainloop() из tkinter имеет контроль все время. И если я запускаю функцию в бесконечном цикле, то mainloop() невозможно выполнить, и графический интерфейс мертв.
Я хотел бы возвращать управление обратно в mainloop () после каждого цикла, но как я могу вернуть управление из mainloop() в runapp-функцию без инициируемого пользователем события?
Вот пример кода, который убивает графический интерфейс:
from Tkinter import *
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame, text="START", command=self.runapp)
self.button.pack(side=LEFT)
self.hi_there = Button(frame, text="RESTART", command=self.restart)
self.hi_there.pack(side=LEFT)
self.runapp()
def restart(self):
print "Now we are restarting..."
def runapp(self):
counter = 0
while (1):
counter =+ 1
time.sleep(0.1)
4 ответов:
Вы найдете ответ в этом другом вопросе Tkinter блокирует python при загрузке значка и tk.mainloop в потоке .
Короче говоря, вам нужно иметь два потока, один для tkinter и один для фоновой задачи.
Программирование на основе событий концептуально просто. Просто представьте, что в конце вашего файла программы находится простой бесконечный цикл:
Таким образом, все, что вам нужно сделать, чтобы постоянно выполнять какую-то небольшую задачу, - это разбить ее на кусочки размером с укус и поместить эти кусочки в очередь событий. Каждый раз, проходя через цикл, следующая итерация Вашего расчета будет выполняться автоматически.while <we have not been told to exit>: <pull an event off of the queue> <process the event>Вы можете поместить объекты в очередь событий с помощью методаafter . Итак, создайте метод это увеличивает число,а затем переносится на несколько миллисекунд позже. Это будет выглядеть примерно так:
def add_one(self): self.counter += 1 self.after(1000, self.add_one)Вышеизложенное будет обновлять счетчик один раз в секунду. Когда ваша программа инициализируется, вы вызываете ее один раз, а затем после этого она вызывает себя снова и снова и т. д.
Этот метод работает только в том случае, если вы можете разбить вашу большую проблему (в вашем случае "считать вечно") на маленькие шаги ("добавить один"). Если вы делаете что-то вроде медленного запроса базы данных или огромного вычисление этот метод не обязательно будет работать.
У меня нет достаточной репутации, чтобы комментировать ответ Брайана Оукли (который я нашел очень эффективным в своей программе), поэтому я добавлю свой опыт здесь. Я обнаружил, что в зависимости от того, как долго ваша фоновая функция работает и насколько точным вы хотите, чтобы интервал времени был, может быть лучше поместить
self.afterвызов в начале повторяющейся функции. В Примере Брайана это выглядело бы какdef add_one(self): self.after(1000, self.add_one) self.counter += 1Выполнение этого способа гарантирует, что интервал времени соблюдается. именно, отрицание любого смещения интервала, которое может произойти, если ваша функция занимает много времени.
Попробуйте понять этот пример: обновление часов в backgroud и обновление GUI (нет необходимости в 2 потоках).
# use Tkinter to show a digital clock # tested with Python24 vegaseat 10sep2006 from Tkinter import * import time root = Tk() time1 = '' clock = Label(root, font=('times', 20, 'bold'), bg='green') clock.pack(fill=BOTH, expand=1) def tick(): global time1 # get the current local time from the PC time2 = time.strftime('%H:%M:%S') # if time string has changed, update it if time2 != time1: time1 = time2 clock.config(text=time2) # calls itself every 200 milliseconds # to update the time display as needed # could use >200 ms, but display gets jerky clock.after(200, tick) tick() root.mainloop( )Кредиты: ссылка на сайт
Comments