繁体   English   中英

Tkinter 带进度条的GUI

[英]Tkinter GUI with progress bar

我在 function 中有一个简单的 Tk GUI 和一个漫长的过程附加到一个按钮。 当我点击按钮时,我想要一个进度条,就像它开始了一个漫长的过程。

我怎样才能做到这一点? 这是我当前的代码:

from tkinter import Button, Tk, HORIZONTAL

from tkinter.ttk import Progressbar
import time


class MonApp(Tk):
    def __init__(self):
        super().__init__()

        bt1 = Button(self, text='Traitement', command=self.traitement)
        bt1.grid()
        self.progress = Progressbar(self, orient=HORIZONTAL, length=100, mode='indeterminate')
        self.progress.grid()
        self.progress.grid_forget()

    def traitement(self):
        self.progress.grid()
        self.progress.start()
        time.sleep(15) 
        ## Just like you have many, many code lines...

        self.progress.stop()


if __name__ == '__main__':
    app = MonApp()
    app.mainloop()

如何在该应用程序中放置进度条?

你可以找到ttk.Progressbartkdocs

from tkinter import *
from tkinter.ttk import *

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

def bar():
    import time
    progress['value']=20
    tk.update_idletasks()
    time.sleep(1)
    progress['value']=50
    tk.update_idletasks()
    time.sleep(1)
    progress['value']=80
    tk.update_idletasks()
    time.sleep(1)
    progress['value']=100

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

最好使用threading并在另一个线程中运行您的代码。

像这样:

from tkinter import Button, Tk, HORIZONTAL

from tkinter.ttk import Progressbar
import time
import threading

class MonApp(Tk):
    def __init__(self):
        super().__init__()


        self.btn = Button(self, text='Traitement', command=self.traitement)
        self.btn.grid(row=0,column=0)
        self.progress = Progressbar(self, orient=HORIZONTAL,length=100,  mode='indeterminate')


    def traitement(self):
        def real_traitement():
            self.progress.grid(row=1,column=0)
            self.progress.start()
            time.sleep(5)
            self.progress.stop()
            self.progress.grid_forget()

            self.btn['state']='normal'

        self.btn['state']='disabled'
        threading.Thread(target=real_traitement).start()

if __name__ == '__main__':

    app = MonApp()
    app.mainloop()

对于要修改自己的所有 GUI 元素(在您的情况下,为了移动进度条),执行必须点击app.mainloop()

在您的情况下, def traitement(self):在不击中主循环的情况下启动然后停止进度条,因此它无法在 GUI 上明显反映预期的进度条移动。 这里的问题是,当执行到达主循环时,进度条被配置为“停止”状态。

因此,在不同的线程上执行耗时的活动是一个好主意,如@xmcp 所示

但是,如果您不想使用线程,则可以使用after方法来实现您想要的:

def stop_progressbar(self):
    self.progress.stop()

def traitement(self):
    self.progress.grid()
    self.progress.start()
    self.after(15000, self.stop_progressbar) 
    ## Call Just like you have many, many code lines...

上面的代码使用了self.after()方法,它会执行stop_progressbar方法在 15 秒后停止,而不是阻塞主线程的 time.sleep ()

tqdm是一个流行的进度条库,它也有对 tkinter 的实验性支持(链接到 API )。 它实际上是ttk.Progressbar的包装器。 用法没有很好的记录(并且有明显的错误)但这是一个最小的工作示例:

from tqdm.tk import tqdm
from time import sleep
from tkinter import Tk, Button   

window = Tk()    

pbar = tqdm(total=30, tk_parent=window)    

def run_task():
    for _ in range(30):
        sleep(0.1)
        pbar.update(1)
    pbar.close() # intended usage, might be buggy
    #pbar._tk_window.destroy() # workaround
    
start_button = Button(window, text="Start", command=run_task)
start_button.pack()
    
window.mainloop()

将在单独的 window 中生成一个进度条,如下所示:

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM