Tkinter: Updating progressbar when a function is called

本小妞迷上赌 提交于 2019-11-30 09:59:37

问题


Imagine the following simple example:

def doNothing():
  sleep(0.5)
  barVar.set(10)
  sleep(0.5)
  barVar.set(20)
  sleep(0.5)
  barVar.set(30)

mainWindow = Tk()
barVar = DoubleVar()
barVar.set(0)
bar = Progressbar(mainWindow, length=200, style='black.Horizontal.TProgressbar', variable=barVar, mode='determinate')
bar.grid(row=1, column=0)
button= Button(mainWindow, text='Click', command=doNothing)
button.grid(row=0, column=0)
mainWindow.mainloop()

What I get when I run this, the progressbar is already at 30% when clicking the button, no progress in front of me. Like attached:

What I need: I can see the progress in front of me (not hanging then suddenly 30%)

Update: I upadted the code according to @Bernhard answer, but still I can not see the progress in front of me. Just a sudden jump of 30% after waiting 1.5 sec

Seocnd Update: I'm only using sleep here as a simulation for a process that takes time, like connecting over ssh and grabing some info.


回答1:


Do not use sleep() in tkinter. The entire reason for you problem is sleep() will freeze tkinter until it is done with its count so what you are seeing is a frozen program and when the program is finally released its already set to 30 percent on the next mainloop update.

Instead we need to use Tkinter's built in method called after() as after is specifically for this purpose.

import tkinter as tk import tkinter.ttk as ttk

mainWindow = tk.Tk()

def update_progress_bar():
    x = barVar.get()
    if x < 100:
        barVar.set(x+10)
        mainWindow.after(500, update_progress_bar)
    else:
        print("Complete")


barVar = tk.DoubleVar()
barVar.set(0)
bar = ttk.Progressbar(mainWindow, length=200, style='black.Horizontal.TProgressbar', variable=barVar, mode='determinate')
bar.grid(row=1, column=0)
button= tk.Button(mainWindow, text='Click', command=update_progress_bar)
button.grid(row=0, column=0)

mainWindow.mainloop()

If you want the bar to appear to move smoothly you will need to speed up the function call and reduce the addition to the DoubbleVar.

import tkinter as tk
import tkinter.ttk as ttk


mainWindow = tk.Tk()

def update_progress_bar():
    x = barVar.get()
    if x < 100:
        barVar.set(x+0.5)
        mainWindow.after(50, update_progress_bar)
    else:
        print("Complete")


barVar = tk.DoubleVar()
barVar.set(0)
bar = ttk.Progressbar(mainWindow, length=200, style='black.Horizontal.TProgressbar', variable=barVar, mode='determinate')
bar.grid(row=1, column=0)
button= tk.Button(mainWindow, text='Click', command=update_progress_bar)
button.grid(row=0, column=0)

mainWindow.mainloop()



回答2:


Because you are calling the function when the buttion is initialized, you need to loose the '(barVar') in the command=(barVar)). This way you bind the function to the button and don't call it when initializing it.

button= Button(mainWindow, text='Click', command=doNothing)

If you need to pass an argument you need to bypass the calling by using lambda:

button= Button(mainWindow, text='Click', command= lambda: doNothing(barVar))



回答3:


I think I find the solution.

simply add mainWindow.update() after each progress. So the final code would be:

def doNothing():
  sleep(0.5)
  barVar.set(10)
  mainWindow.update()
  sleep(0.5)
  barVar.set(20)
  mainWindow.update()
  sleep(0.5)
  barVar.set(30)
  mainWindow.update()


来源:https://stackoverflow.com/questions/51298758/tkinter-updating-progressbar-when-a-function-is-called

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!