简体   繁体   English

如何从另一个线程中的 Flask 应用程序更新 tkinter window 中的进度条值?

[英]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.我有一个在数据库中插入一些数据的Flask应用程序。 While the insertion is in progress, I want a progress bar to show how many data were inserted (so, I use the determinate mode).在插入过程中,我想要一个进度条来显示插入了多少数据(因此,我使用determinate模式)。 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. 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.当我运行这部分时,进度条会更新,但我必须手动关闭 window 才能开始导入。 After each import, the window appears, with the progress bar showing... progress.每次导入后,都会出现 window,进度条显示...进度。 Obviously, this is from mainloop() .显然,这是来自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?我应该怎么做,因为我不必在每次迭代时手动关闭 window?

Later edit: a very important fact is that tkinter must run in the main thread.稍后编辑:一个非常重要的事实是tkinter必须在主线程中运行。 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.您是否尝试过将主循环从 function 中取出。 Because now each time you call on the progress bar, it creates a new tk() instance.因为现在每次调用进度条时,它都会创建一个新的 tk() 实例。

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.编辑 1:下面的代码提供了两个函数,说明您似乎可以通过启动新的主循环来“更新”tkinter。 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:编辑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.要修复它,您需要在 for 循环之前创建一个主循环。 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) .不要忘记在 function show_progress_window(Add root to the end)的括号之间添加“root”。 And remove the mainloop from the function.并从 function 中移除主循环。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM