python - 如何在其他函数完成执行后调用 tkinter 中的函数?
问题描述
你好,
我知道事件驱动编程与程序顺序执行指令的“传统编程”非常不同。但是,我是新手,我不理解 100% 事件驱动编程是如何工作的,我认为这就是我在这里遇到问题的原因。
我从这篇文章的答案中构建了一个示例:tkinter progress bar won't update when called from an other app
在此示例中,我希望我的程序在完成扫描给定路径后执行一个操作。天真地,我尝试在调用action
之后添加对例程的调用walk
:
import sys
import os
import tkinter as tk
import tkinter.ttk as ttk
from tkinter.filedialog import askdirectory
class App(ttk.Frame):
def __init__(self, parent, title):
#tk.Frame.__init__(self, parent)
super(App, self).__init__(parent)
parent.wm_withdraw()
parent.wm_title(title)
self.create_ui()
self.grid(sticky = "news")
parent.wm_protocol("WM_DELETE_WINDOW", self.on_destroy)
parent.grid_rowconfigure(0, weight=1)
parent.grid_columnconfigure(0, weight=1)
parent.wm_deiconify()
def create_ui(self):
textframe = ttk.Frame(self)
self.text = text = tk.Text(textframe)
vs = ttk.Scrollbar(textframe, orient=tk.VERTICAL, command=text.yview)
text.configure(yscrollcommand=vs.set)
text.grid(row=0, column=0, sticky=tk.NSEW)
vs.grid(row=0, column=1, sticky=tk.NS)
textframe.grid_columnconfigure(0, weight=1)
textframe.grid_rowconfigure(0, weight=1)
textframe.grid(row=0, column=0, columnspan=2, sticky=tk.NSEW)
self.progressvar = tk.IntVar()
self.progress = ttk.Progressbar(self, variable=self.progressvar)
test_button = ttk.Button(self, text="Walk", command=self.on_walk)
exit_button = ttk.Button(self, text="Exit", command=self.on_destroy)
self.progress.grid(row=1, column=0, sticky=tk.NSEW)
test_button.grid(row=1, column=0, sticky=tk.SE)
exit_button.grid(row=1, column=1, sticky=tk.SE)
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
def on_destroy(self):
self.master.destroy()
def on_walk(self):
root = askdirectory()
self.walk(root)
self.action()
def walk(self, root=None):
if root:
# this is potentially costly, but how to find the number of files to be examined?
count = sum([len(files) for (root,dirs,files) in os.walk(root)])
self.text.delete("1.0", "end")
self.progress.configure(maximum=count)
self.progressvar.set(0)
walker = os.walk(root)
self.after(100, self.do_one, walker)
def do_one(self, walker):
try:
root,dirs,files = next(walker)
for file in files:
self.text.insert(tk.END, os.path.join(root, file), "PATH", "\n", "")
self.text.see(tk.END)
self.progressvar.set(self.progressvar.get() + 1)
self.after(10, self.do_one, walker)
except StopIteration:
pass
def action(self):
print('DO SOMETHING HERE, AFTER WALK HAS FINISHED\n')
通过这样做,action
函数在 walk 调用结束之前被调用。
action
我通过在函数中的异常后调用找到了一种解决方法do_one
:
def do_one(self, walker):
try:
root,dirs,files = next(walker)
for file in files:
self.text.insert(tk.END, os.path.join(root, file), "PATH", "\n", "")
self.text.see(tk.END)
self.progressvar.set(self.progressvar.get() + 1)
self.after(10, self.do_one, walker)
except StopIteration:
self.action()
我想有更好的方法来做到这一点。有没有办法创建一个事件来告诉程序执行的任务walk
已经完成?
谢谢
解决方案
推荐阅读
- sql - postgreSQL:使用 WHERE .. LIKE 在列上分隔函数
- macos - 即使执行了协同设计过程,应用程序在 macOS High Sierra 10.13.6 中意外退出?
- android - Android撰写约束布局问题
- language-construct - 变量重载
- azure-devops - Azure DevOps Rest Api 是否返回正确数量的 pullrequest?
- javascript - 通过使用jquery选择跨度的第n个:div的不同背景颜色
- html - 如何在单击时更改单选按钮的背景颜色(联系表格 7)
- spring - 如何在 Spring Integration 中写回套接字
- docker - 在 Nvidia + Cuda 期间未找到 NVIDIA 驱动程序 - Docker 映像构建
- arrays - 如何将存储在 Postgres 中的图像的图像 URL 插入 Spring Boot 模型