Tkinter进度条

时间:2018-03-15 10:40:51

标签: python tkinter python-multithreading

我通过互联网查看并无法得到答案,如果我有一个CPU使用率很高的进程,我想在它运行时提供一个进度条(所以程序不会进入可能在另一个线程上“没有响应”的状态,我该怎么做?

2 个答案:

答案 0 :(得分:1)

解决方案应该是这样的:

您至少有2个帖子, threadA threadB

  • ThreadA 是调用mainloop()的线程以及进度条所在的位置。
  • ThreadB 是您的繁重程序处理他的东西的线程。

当每件事开始时:

  • ThreadB 将消息放入共享队列
    • (这样ThreadB告诉ThreadA它不在"没有响应"状态)
  • ThreadA 从共享队列中获取消息并更新进度条
    • (这样ThreadA告诉用户ThreadB不在"没有响应"状态)

这是一种非常通用的解决方案模式 如果你试着写下一些实现这种模式的代码,请发布它,我会尽力帮助。

这里有一些参考:

修改

这是一般解决方案的完整示例。 我希望这会有所帮助。

import tkinter as tk
from tkinter import ttk

import threading
import queue

import time

shared_queue = queue.Queue()

def thread1_main():
    tot_time = 5 # seconds

    elapsed_time = 0

    while(True):
        time.sleep(1)
        shared_queue.put("I'm working")
        elapsed_time += 1
        if(elapsed_time > tot_time):
            break;

    shared_queue.put("task done")

def updates_progress_bar():
    try:
        msg = shared_queue.get(block=False)
    except queue.Empty:
        msg = None
    else:
        # do update the progress bar here
        delta = 1
        val = bar_value.get()+delta
        val = val if val <= bar["maximum"] else 0
        bar_value.set(val)

    if(msg != "task done"):
        root.after(500, updates_progress_bar)
    else:
        print(msg)

if(__name__ == "__main__"):
    root = tk.Tk()
    root.wm_geometry("200x200")

    root.rowconfigure(0, weight=1)
    root.columnconfigure(0, weight=1)

    bar_value = tk.IntVar()
    bar = ttk.Progressbar(  root,
                            maximum=3, length=100, variable=bar_value)
    bar.grid(row=0, column=0, sticky="we", padx=5) 

    shared_queue = queue.Queue()
    thread1 = threading.Thread(target=thread1_main)
    thread1.deamon = True
    thread1.start()

    root.after(500, updates_progress_bar)

    root.mainloop()

    print("that's all folks")

答案 1 :(得分:0)

这是一个具有无限操作模式的原始进度条实现。它不会在线程中运行,因为它确实应该。如果将此集成在一个没有进行繁重工作的线程中,并向该线程发送停止消息,则该过程将停止。此示例使用计时器来停止进度条,但您也可以使用任何事件。

import tkinter as tk
from tkinter import ttk
import sys

class MyProgress(tk.Frame):

    def __init__(self, parent, **kwargs):
        tk.Frame.__init__(self, parent)
        self.pack()
        label = tk.Label(self, text="Progress:", anchor='w')
        label.pack(side='left')
        self.progress = ttk.Progressbar(self)
        for attribute,value in kwargs.items():
            try:
                self.progress[attribute] = value
            except:
                print("Attribute error:", attribute)
                print("Try one of:")
                print(self.progress.configure())
                sys.exit()
        self.progress.pack(side='left')
        self.running = False
        self.parent = parent

    def start(self):
        self.running = True
        self.increaseProgress()

    def stop(self):
        self.running = False
        print("End of Job")

    def increaseProgress(self):
        if not self.running:
            return
        self.progress['value'] += 1
        self.parent.after(100, self.increaseProgress)


if __name__ == '__main__':
    root = tk.Tk()
    app = MyProgress(root, mode='indeterminate', maximum=10, length=100, value=0)
    app.start()
    # Trigger a stop after 5 seconds
    root.after(5000, app.stop)
    root.mainloop()