如何将进度条连接到函数? [英] How to connect a progress bar to a function?

查看:53
本文介绍了如何将进度条连接到函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将进度条连接到我的项目的功能.

I'm trying to connect a progress bar to a function for my project.

这是我目前所拥有的,但我很确定它没有任何作用:

This is what I have so far but im pretty sure it does nothing:

def main():
    pgBar.start()
    function1()
    function2()
    function3()
    function4()
    pgBar.stop()

这是我制作进度条的代码,如果有帮助的话:

Here is the code where I make my progress bar if that helps at all:

pgBar = ttk.Progressbar(window, orient = HORIZONTAL, length=300, mode = "determinate")
pgBar.place(x=45, y=130)

我一直在做一些研究并了解到在运行函数或类似的东西时 tkinter 窗口会冻结.有没有办法可以在主函数内部调用的每个函数结束时解冻"窗口?

I have been doing some research and understand that the tkinter window freezes when running a function or something like that. Is there a way I could "unfreeze" the window at the end of each function that is called inside the main one?

推荐答案

由于 tkinter 是单线程,您需要另一个线程来执行您的 main 函数而不冻结 GUI.一种常见的方法是工作线程将消息放入同步对象中(例如 Queue),GUI 部分使用此消息,更新进度条.

Since tkinter is single threaded, you need another thread to execute your main function without freezing the GUI. One common approach is that the working thread puts the messages into a synchronized object (like a Queue), and the GUI part consumes this messages, updating the progress bar.

以下代码基于 ActiveState 上完整详细的示例:

The following code is based on a full detailed example on ActiveState:

import tkinter as tk
from tkinter import ttk
import threading
import queue
import time


class App(tk.Tk):

    def __init__(self):
        tk.Tk.__init__(self)
        self.queue = queue.Queue()
        self.listbox = tk.Listbox(self, width=20, height=5)
        self.progressbar = ttk.Progressbar(self, orient='horizontal',
                                           length=300, mode='determinate')
        self.button = tk.Button(self, text="Start", command=self.spawnthread)
        self.listbox.pack(padx=10, pady=10)
        self.progressbar.pack(padx=10, pady=10)
        self.button.pack(padx=10, pady=10)

    def spawnthread(self):
        self.button.config(state="disabled")
        self.thread = ThreadedClient(self.queue)
        self.thread.start()
        self.periodiccall()

    def periodiccall(self):
        self.checkqueue()
        if self.thread.is_alive():
            self.after(100, self.periodiccall)
        else:
            self.button.config(state="active")

    def checkqueue(self):
        while self.queue.qsize():
            try:
                msg = self.queue.get(0)
                self.listbox.insert('end', msg)
                self.progressbar.step(25)
            except Queue.Empty:
                pass


class ThreadedClient(threading.Thread):

    def __init__(self, queue):
        threading.Thread.__init__(self)
        self.queue = queue

    def run(self):
        for x in range(1, 5):
            time.sleep(2)
            msg = "Function %s finished..." % x
            self.queue.put(msg)


if __name__ == "__main__":
    app = App()
    app.mainloop()

由于 ActiveState 上的 原始示例 有点混乱 IMO(ThreadedClient 是与 GuiPart 非常结合,并且诸如控制从 GUI 生成线程的时刻之类的事情并不像他们想象的那么简单),我已经对其进行了重构并添加了一个按钮来启动新线程.

Since the original example on ActiveState is a bit messy IMO (the ThreadedClient is quite coupled with the GuiPart, and things like controlling the moment to spawn the thread from the GUI are not as straightforward as they could be), I have refactored it and also added a Button to start the new thread.

这篇关于如何将进度条连接到函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆