Python匹配进度条到长进程

时间:2018-04-21 13:40:48

标签: python tkinter progress-bar

我有一个Python脚本,其中有一些过程需要一些时间,例如创建.shp文件和打开.mxd。我已阅读Python Progress Bar,但我想避免使用外部包。到目前为止,我有;

C().f()

它似乎有效但我不认为打开.mxd的过程正在关注进度条处于什么阶段。我想得到它,以便过程完成与进度条达到100%一致。有没有让这个过程等待'进度条?任何人都可以提供一些关于如何使其工作的指示? 感谢

1 个答案:

答案 0 :(得分:0)

问题是您在bar功能中调用的睡眠功能和可能的任何其他阻塞功能会阻止GUI。解决方案可能是将操作推送到工作线程。我能想到的一个非常快速的解决方案是:

from random import randint
from threading import Thread
from tkinter import Tk, DoubleVar, HORIZONTAL
from tkinter.ttk import Frame, Button, Progressbar
from time import sleep

class Worker(Thread):
    def __init__(self, reference):
        super().__init__()
        self.reference = reference

    def run(self):
        print("running...")
        # replace this dummy loop with actual processing tasks
        while self.reference.get_progress() < 100:
            duration = randint(1, 3)
            sleep(duration)
            self.reference.add_progress(10 * duration)
        print("finished.")

class Example(Frame):
    def __init__(self, root):
        super().__init__(master=root)
        self.progress = DoubleVar(value=0.0)
        self.worker = Worker(reference=self)
        self.startbutton = Button(master=self, text="Start", command=self.start)
        self.startbutton.pack()
        self.progressbar = Progressbar(master=self, orient=HORIZONTAL, length=100, mode='determinate', variable=self.progress)
        self.progressbar.pack()
        self.infobutton = Button(master=self, text="Info", command=self.info)
        self.infobutton.pack()
        self.pack()

    def get_progress(self):
        return self.progress.get()

    def set_progress(self, value):
        self.progress.set(value)

    def add_progress(self, value):
        self.progress.set(self.progress.get() + value)

    def start(self):
        # print("sleeping...")
        # sleep(10)  # uncomment this to block the GUI
        print("starting...")
        self.worker.start()

    def info(self):
        print(self.worker.is_alive())

def main():
    root = Tk()
    app = Example(root)
    app.mainloop()

if __name__ == '__main__':
    main()

请注意,信息按钮在线程运行之前,之间和之后都有效。这个快速解决方案的一个问题是线程只能运行一次。要多次运行,需要进行某种重置。