【问题标题】:Tkinter GUI with progress bar带有进度条的 Tkinter GUI
【发布时间】:2015-11-17 22:48:13
【问题描述】:

我有一个简单的 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()

如何在该应用程序中添加进度条?

【问题讨论】:

标签: python tkinter


【解决方案1】:

你可以在tkdocs找到ttk.Progressbar

import time
from tkinter import *
from tkinter.ttk import *

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


def bar():
    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 并在另一个线程中运行您的代码。

像这样:

import threading
import time
from tkinter import Button, Tk, HORIZONTAL
from tkinter.ttk import Progressbar

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

【讨论】:

  • 感谢您的回答。我不想在用户单击 EXE 按钮之前显示进度条...是不是我不明白,如何显示进度条您所在的位置-> def sous_ens... 我试着放fonction sous_ens 代码中的进度条,看来只有我离开了 fonction...
  • 只有pack(或grid)当你想显示进度条实例并使用pack_forget(或grid_forget)隐藏它。
  • 非常感谢。把我不明白怎么...
  • 您的代码几乎是正确的。只需使用threading 库并在另一个线程中运行traitement。查看我的更新答案。
  • 顺便说一句,这使用了 ttk 按钮而不是 tkinter 按钮,因为您在导入 ttk 之后,它会覆盖 tkinter 按钮类。
【解决方案2】:

要让所有 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() 阻塞主线程。

【讨论】:

  • 您不必在 tkinter 应用程序中使用 mainloop。您可以使用 while true 循环更新窗口...它也可以工作(关闭窗口时出现错误除外)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-28
  • 2015-06-21
  • 1970-01-01
  • 2013-05-04
  • 1970-01-01
相关资源
最近更新 更多