python - How to update the progress bar value in a tkinter window from a Flask application which is in another thread?
问题描述
I have a Flask
application that inserts some data in a database. While the insertion is in progress, I want a progress bar to show how many data were inserted (so, I use the determinate
mode). Knowing that Flask
and tkinter
do not go together well proof, I decided to show the tkinter
window in a separate thread, the main thread being the Flask
application.
Here is my code so far
import tkinter as tk
from multiprocessing import Process
from tkinter.ttk import Progressbar, Button
import global_library
from application import config
from application.admin import add_match as a
from application.xml import create_string as cs
from application.xml import dl_xml_file as dl
from application.xml import xml_parsing as xp
def show_progress_window(low_end, high_end, match_count):
root = tk.Tk()
progress_bar = Progressbar(root, mode='determinate', orient='horizontal', length=200)
progress_bar['maximum'] = high_end - low_end
progress_bar['value'] = match_count
progress_bar.pack()
cancel_button = Button(root, text='Anulare')
cancel_button.pack()
root.mainloop()
def import_engine(low_end, high_end):
file = config['DEFAULT']['PROTECTED_RESOURCE_PATH']
for match_id in range(low_end, high_end + 1, 1):
p = Process(target=show_progress_window, args=(low_end, high_end, match_id - low_end))
p.start()
p.join()
params = cs.create_match_details_string(match_id)
dl.download_xml_file(file, params, global_library.details_savepath)
match_details = xp.parse_match_details_file(match_id)
a.add_a_match(match_details[0], match_details[1], match_details[2], match_details[3], match_details[4],
match_details[5], match_details[6], match_details[7], match_details[8], match_details[9],
match_details[10], match_details[11], match_details[12], match_details[13], match_details[14],
match_details[15], match_details[16])
When I run this part, the progress bar updates, but I have to manually close the window for the importing to begin. After each import, the window appears, with the progress bar showing... progress. Obviously, this is from mainloop()
. As obvious, I cannot suppres this method.
Where am I mistaking? What should I do so as I don't have to manually close the window at each iteration?
Later edit: a very important fact is that tkinter
must run in the main thread. If it doesn't, the progress bar will not update no matter what.
解决方案
Okay, my first answer made no sense. Have you tried taking the mainloop out of the function. Because now each time you call on the progress bar, it creates a new tk() instance.
something lke this:
root = tkinter.Tk()
# call your function and pass "root" to it as well
root.mainloop()
Edit 1: The code below provides two functions illustrating that it seems you can 'update' tkinter by starting a new mainloop. But that's not the case.
import tkinter as tk
def looptk(min,max,progress):
root=tk.Tk()
label = tk.Label(root, text=progress).pack()
root.mainloop()
print(id(root))
def looptk2(min,max,progress,root):
label = tk.Label(root, text=progress).pack()
print(id(root))
min = 0
max = 6
i = 0
while i < max:
looptk(1,5,i)
i += 1
root=tk.Tk()
min = 0
max = 6
i = 0
while i < max:
looptk2(1,5,i,root)
i += 1
root.mainloop()
Edit 2:
Here is where you call the mainloop several times:
for match_id in range(low_end, high_end + 1, 1):
p = Process(target=show_progress_window, args=(low_end, high_end, match_id - low_end))
To fix it you need to create a mainloop before that for loop. Change it to something like this:
root = tk.tk()
for match_id in range(low_end, high_end + 1, 1):
p = Process(target=show_progress_window, args=(low_end, high_end, match_id - low_end,root))
root.mainloop()
Don't forget to add "root" between the brackets of the function show_progress_window(Add root to the end)
.
And remove the mainloop from the function.
推荐阅读
- jquery - 我如何计算图像的口粮宽度和高度
- python - jupyter notebook 中的警告和错误到底有什么区别?
- python - 在 Keras 中保存模型时是否应该单独保存权重?
- javascript - 数组帮助。如何将数组本身相乘,一个中没有第一个元素,另一个中没有最后一个元素
- go - 如何使用反射从另一个函数创建新函数
- python - CX_Freeze 不设置图标
- c# - 来自 AES 解密的无法识别的 unicode 结果
- elixir - 频道在测试环境中收不到本地广播
- r - 错误 pgmm 函数:矩阵的行数必须匹配
- c# - 从 asp.net 中的数据库获取值后将下拉值转换为 DateTime