TkInter:如何等待方法完成后的回调 [英] TkInter: how to wait until callback from after method has completed

查看:35
本文介绍了TkInter:如何等待方法完成后的回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 Tkinter .after 方法时,代码继续传递,无需等待回调完成.

导入 tkinter 作为 tk将 tkinter.ttk 导入为 ttk导入时间从日期时间导入日期时间全球我我 = 0全局 jj = 0def SomeFunction():全球我对于范围内的数量(10):我+=1x = barVar.get()barVar.set(x+5)histrun_mainWindow.update()时间.sleep(2)def SecondFunction():全局 j对于范围内的数量(10):j+=1x = barVar.get()barVar.set(x+5)histrun_mainWindow.update()时间.sleep(2)定义加载(运行日期):histrun_mainWindow.after(50, SomeFunction)histrun_mainWindow.after(50, SecondFunction)全局 i, j打印 '数字是:', i + jhistrun_mainWindow = tk.Tk()run_date = datetime.today().date()barVar = tk.DoubleVar()barVar.set(0)bar = ttk.Progressbar(histrun_mainWindow, length=200, style='black.Horizo​​ntal.TProgressbar', variable=barVar, mode='确定')bar.grid(行=1,列=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

进度条继续更新,所以我知道在打印 i 后在后台继续调用 Load

解决方案

问题:进度条不更新 - 窗口冻结,直到所有功能完成

使用线程来防止主循环冻结.
您的函数 - SomeFunctionSecondFunction - 也可能在 global 命名空间中.
然后你必须通过 self.pbar 作为参数,例如SomeFunction(pbar): ... f(self.pbar).

<小时><块引用>

注意:
你看到一个 RuntimeError: main thread is not in main loop
如果.destroy()App() 窗口,而Thread 正在运行

导入 tkinter 作为 tk进口螺纹类应用程序(tk.Tk):def __init__(self):super().__init__()btn = tk.Button(self, text='Run',命令=lambda :threading.Thread(target=self.Load).start())btn.grid(row=0, column=0)self.pbar = ttk.Progressbar(self,maximum=2 *(5 * 5), mode='确定')self.pbar.grid(row=1, column=0)def SomeFunction(self):对于范围内的 num(5):print('SomeFunction({})'.format(num))self.pbar['value'] += 5时间.睡眠(1)返回编号def SecondFunction(self):对于范围内的 num(5):print('SecondFunction({})'.format(num))self.pbar['value'] += 5时间.睡眠(1)返回编号def 加载(自己):数字 = 0对于 [self.SomeFunction, self.SecondFunction] 中的 f:数字 += f()print('数字是:{}'.format(number))如果 __name__ == "__main__":应用程序().主循环()

<块引用>

输出:

SomeFunction(0)一些函数(1)一些函数(2)一些函数(3)一些函数(4)第二功能(0)第二功能(1)第二功能(2)第二功能(3)第二功能(4)数字是:8

使用 Python 测试:3.5*)无法使用 Python 2.7 进行测试

When using the Tkinter .after method, the code continues passed without waiting for the callback to complete.

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()

This example shows what is happening. The .after() calls the Load() function but doesn't wait for Load() to complete, it goes straight on to the next line.

I want i to print as 10 but because the .after() doesn't wait for Load() to finish it's additions, i prints as 0

The progress bar continues to update so I know that Load was called as it continues in the background after i is printed

解决方案

Question: the progress bar doesn't update - the window freezes until all functions have completed

Use a Thread to prevent main loop from freezing.
Your functions - SomeFunction, SecondFunction - may also in global namespace.
Then you have to pass self.pbar as paramter, e.g. SomeFunction(pbar): ... f(self.pbar).


Note:
You see a RuntimeError: main thread is not in main loop
if you .destroy() the App() window while the Thread is running!

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()

Output:

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

Tested with Python: 3.5 *)Could not test with Python 2.7

这篇关于TkInter:如何等待方法完成后的回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆