TkInter: как ждать обратного вызова после завершения метода - PullRequest
2 голосов
/ 26 апреля 2019

При использовании метода Tkinter .after код продолжается, не дожидаясь завершения обратного вызова.

import tkinter as tk
import tkinter.ttk as ttk
import time
from datetime import datetime

global i
i = 0
global j
j = 0

def SomeFunction():
    global i
    for num in range(10):
        i+=1
        x = barVar.get()
        barVar.set(x+5)
        histrun_mainWindow.update()
        time.sleep(2)

def SecondFunction():
    global j
    for num in range(10):
        j+=1
        x = barVar.get()
        barVar.set(x+5)
        histrun_mainWindow.update()
        time.sleep(2)

def Load(run_date):
    histrun_mainWindow.after(50, SomeFunction)
    histrun_mainWindow.after(50, SecondFunction)
    global i, j 
    print 'Number is :', i + j

histrun_mainWindow = tk.Tk()
run_date = datetime.today().date()
barVar = tk.DoubleVar()
barVar.set(0)
bar = ttk.Progressbar(histrun_mainWindow, length=200, style='black.Horizontal.TProgressbar', variable=barVar, mode='determinate')
bar.grid(row=1, column=0)
button= tk.Button(histrun_mainWindow, text='Run for this date ' + str(run_date), command=lambda:Load(run_date))
button.grid(row=0, column=0)
histrun_mainWindow.mainloop()

Этот пример показывает, что происходит. .After () вызывает функцию Load (), но не ожидает завершения Load (), а сразу переходит к следующей строке.

Я хочу, чтобы я печатал как 10, но, поскольку .after () не ждет, пока Load () завершит свои добавления, я печатаю как 0

Индикатор выполнения продолжает обновляться, поэтому я знаю, что Load была вызвана, так как она продолжается в фоновом режиме после того, как я напечатан

1 Ответ

0 голосов
/ 26 апреля 2019

Вопрос: индикатор выполнения не обновляется - окно останавливается до завершения всех функций

Используйте Thread для предотвращения main loop от заморозка .
Ваши функции - SomeFunction, SecondFunction - могут также находиться в global пространстве имен.
Тогда вам нужно передать self.pbar в качестве параметра, например SomeFunction(pbar): ... f(self.pbar).


Примечание :
Вы видите RuntimeError: main thread is not in main loop
, если вы .destroy() окно App(), в то время как Threadработает !

import tkinter as tk
import threading

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        btn = tk.Button(self, text='Run', 
                              command=lambda :threading.Thread(target=self.Load).start())
        btn.grid(row=0, column=0)
        self.pbar = ttk.Progressbar(self, maximum=2 *(5 * 5), mode='determinate')
        self.pbar.grid(row=1, column=0)

    def SomeFunction(self):
        for num in range(5):
            print('SomeFunction({})'.format(num))
            self.pbar['value'] += 5
            time.sleep(1)
        return num

    def SecondFunction(self):
        for num in range(5):
            print('SecondFunction({})'.format(num))
            self.pbar['value'] += 5
            time.sleep(1)
        return num

    def Load(self):
        number = 0
        for f in [self.SomeFunction, self.SecondFunction]:
            number += f()
        print('Number is :{}'.format(number))

if __name__ == "__main__":
    App().mainloop()

Выход :

SomeFunction(0)
SomeFunction(1)
SomeFunction(2)
SomeFunction(3)
SomeFunction(4)   
SecondFunction(0)
SecondFunction(1)
SecondFunction(2)
SecondFunction(3)
SecondFunction(4)
Number is :8

Протестировано с Python:3,5 *) Не удалось протестировать с Python 2.7

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...