Python 使用进度条显示函数的执行进度

Python 使用进度条显示函数的执行进度,python,function,tkinter,progress-bar,execution-time,Python,Function,Tkinter,Progress Bar,Execution Time,我有一个计算两个整数之和的函数。我想用tkinter进度条显示这个sum函数的执行状态 这是我的方法,但它在执行sum函数后显示进度条,我想在sum函数执行时显示进度条,进度应该根据函数的执行时间来指示 我没有找到满足我要求的答案。如果有人能帮我,那就太好了。你的问题很有趣,但你的方法是完全错误的。 它首先执行sum,因为GUI尚未到达mainloop 所以,在GUI到达mainloop之后,它开始等待事件,因为GUI编程的事件驱动特性,比如按钮按下。换句话说:如果请求回调tkinter,则在m

我有一个计算两个整数之和的函数。我想用tkinter进度条显示这个sum函数的执行状态

这是我的方法,但它在执行sum函数后显示进度条,我想在sum函数执行时显示进度条,进度应该根据函数的执行时间来指示


我没有找到满足我要求的答案。如果有人能帮我,那就太好了。

你的问题很有趣,但你的方法是完全错误的。 它首先执行sum,因为GUI尚未到达mainloop

所以,在GUI到达mainloop之后,它开始等待事件,因为GUI编程的事件驱动特性,比如按钮按下。换句话说:如果请求回调tkinter,则在mainloop之前不能调用函数

另一个问题是tkinter是单线程的,因此gui只能在函数运行结束时进行自我更新。所以,若您在函数中启动一个循环,那个么也并没有对gui的回调,但您可以从循环中调用函数,并在每次迭代中更新gui!e、 g.自生成事件的循环,由生成事件或之后的方法组成

看在上帝的份上,若函数并没有完全执行,progressbar怎么知道函数的执行时间呢?如果有人知道,请发表评论

但如果你敢,你可以开始玩多线程和队列

在我的示例中,进度条与函数的执行并行更新,这要归功于执行函数的独立线程,以及函数响应所在的队列,进度条是根据该队列更新的

使用python 3.5对其进行了测试:

import sys
import ttk
from Tkinter import *
from timeit import default_timer as timer


def sum(a, b):
    for i in range(10):
        c = a + b
        print "Sum", c
        time.sleep(5)
    return c


mGui = Tk()
mGui.title('Progress')
mpb = ttk.Progressbar(mGui,orient ="horizontal", length = 200, mode ="determinate")
mpb.pack()
mpb.start()
mpb["maximum"] = 100


Start_Timer=timer()
sum(3,4)
Stop_Timer=timer()
Execution_Time=Stop_Timer-Start_Timer
mpb["value"] = Execution_Time
mGui.mainloop()
链接:

try:
    import Tkinter as tk              # Python 2
    import ttk
    import Queue as queue
except ImportError:
    import tkinter as tk              # Python 3
    import tkinter.ttk as ttk
    import queue

import threading
import time


class ThreadFunc(threading.Thread):
    def __init__(self, loop_time=1.0 / 60):
        super(ThreadFunc, self).__init__()
        self.queue = queue.Queue()
        self.timeout = loop_time
        self.parent = None
        self.stop_on_complete = None
        self.running = False
        self._stop = threading.Event()

    def start_thread(self, parent, stop_on_complete=False):
        # thread can wait for functions if not stop_on_complete
        self.parent = parent
        self.stop_on_complete = stop_on_complete
        self.running = True
        self.start()

    def put_function(self, function, *args, **kwargs):
        # put another function in queue
        self.queue.put((function, args, kwargs))

    def run(self):
        print('### STARTED ###')
        while self.running:
            try:
                function, args, kwargs = self.queue.get(timeout=self.timeout)
                print('### RUNNING ###')
                function(*args, **kwargs)
            except queue.Empty:
                if self.stop_on_complete:
                    self.stop()
                else:
                    self.idle()

    def stop(self):
        print('### STOPPED ###')
        self.running = False
        self._stop.set()

    @staticmethod
    def idle():
        print('### IDLE ###')


class App(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.resizable(width=False, height=False)
        self.minsize(width=400, height=25)
        self.wm_title('Another SO Example with progressbar')
        self.queue = queue.Queue()
        self.thread = None
        self.in_work = False

        self.mpb_frame = tk.Frame(self)
        self.mpb = ttk.Progressbar(self.mpb_frame, orient='horizontal', length=400, mode='determinate')
        self.mpb.pack()
        self.mpb_frame.pack()

        self.mpb.bind('<Map>', self.start_example)

    def start_example(self, event=None):
        if self.in_work:
            return
        self.in_work = True
        self.spawn_thread(sum_func, 4, 3, self.queue)

    def spawn_thread(self, command, *args):
        # spawn a thread
        self.thread = ThreadFunc()
        self.thread.start_thread(self, True)
        self.thread.put_function(command, *args)
        self.periodic_call()

    def periodic_call(self):
        # check if our thread is running and if so - update progressbar
        self.check_queue()
        try:
            self.thread.is_alive()
            self.after(100, self.periodic_call)
        except TypeError:
            self.in_work = False
            self.quit()

    def check_queue(self):
        # "transfer" messages to mpb-progressbar steps (10 iteration over you sum)
        while self.queue.qsize():
            try:
                self.queue.get(0)
                self.mpb.step(10)
            except queue.Empty:
                pass


def sum_func(a, b, queue_local):
    # your sum function
    for i in range(10):
        c = a + b
        time.sleep(1)
        queue_local.put(c)
        print('Sum', c)


app = App()
app.mainloop()