【问题标题】:Display the progress of execution of a function using a progress bar使用进度条显示函数的执行进度
【发布时间】:2017-08-04 00:27:43
【问题描述】:
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()

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

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

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

【问题讨论】:

    标签: python function tkinter progress-bar execution-time


    【解决方案1】:

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

    所以在 GUI 到达 mainloop 之后,它开始等待事件(由于 GUI 编程的事件驱动性质),例如按钮按下。换句话说:如果你要求回调 tkinter,你不能在 mainloop 之前调用函数。

    另一个问题 - tkinter 是单线程的,因此 gui 只能在函数完成运行时自行更新。因此,如果您在函数中启动一个循环,则也不会对 gui 进行回调,但您可以从循环中调用函数,并在每次迭代时更新 gui! (例如,自生成事件的“循环”,由方法 generate_eventafter 组成。)

    看在上帝的份上,如果函数没有完全执行,进度条如何知道函数的执行时间?如果有人知道,请发表评论..

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

    在我的示例中,进度条与函数的执行并行更新,这要归功于执行函数的单独线程以及函数的“响应”所在的队列,基于其中进度条正在更新!

    用 python 3.5 测试过:

    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()
    

    链接:

    【讨论】:

      猜你喜欢
      • 2013-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多