【问题标题】:Python match progress bar to long processPython将进度条匹配到长进程
【发布时间】:2018-04-21 13:40:48
【问题描述】:

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

    from tkinter import *
from tkinter.ttk import *
import os, arcpy

tk=Tk()
progress=Progressbar(tk,orient=HORIZONTAL,length=100,mode='determinate')

def bar():
    import time
    os.startfile("Assignment.mxd")
    progress['value']=20
    tk.update_idletasks()
    time.sleep(8)
    progress['value']=50
    tk.update_idletasks()
    time.sleep(8)
    progress['value']=80
    tk.update_idletasks()
    time.sleep(8)
    progress['value']=100


progress.pack()
Button(tk,text='Open',command=bar).pack()
mainloop()

它似乎正在工作,但我认为打开 .mxd 的过程并未关注进度条处于哪个阶段。我想得到它,以便过程完成与进度条达到 100% 一致。是否可以让进程“等待”进度条?任何人都可以提供一些关于我如何让它工作的指示吗? 谢谢

【问题讨论】:

  • 您有什么方法可以查明 mxd 进程取得了多少进展?

标签: python tkinter progress-bar


【解决方案1】:

问题是睡眠函数和您在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()

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

【讨论】:

  • 感谢 Lukisn 但我收到此错误; TypeError: super() 至少需要 1 个参数(给定 0)
  • Python 2?我的代码是 Python 3。试试 Frame.__init__(...) 和 Thread.__init__。
  • 嗨 Lukisn 是的,我正在使用 Python 2.7.13。你的意思是 - class Example(Frame): def Frame__init__(self, root): ?抱歉,我还是 Python 的初学者。
  • Thread.__init__(self) ind Worker 类,Frame.__init__(self, master=root) 在 Example 类中。
  • 感谢 Lukisn 的帮助,但我会尝试让这段代码正常工作; stackoverflow.com/questions/25202147/…。这里的例子对我来说有点太复杂了。还是谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多