Reputation: 11
I have made a script that calles certain functions. After every function I want to update my progress bar. This is my code of the progressbar:
class loading(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
s = ttk.Style()
s.theme_use('clam')
s.configure("red.Horizontal.TProgressbar", foreground='red', background='red')
self.progress = ttk.Progressbar(self, style="red.Horizontal.TProgressbar", orient='horizontal',
length=101, mode='determinate')
self.progress.pack(pady=10)
def updateprogress(self):
self.progress.step(20)
return
But when I try to call update progress after my script functions, it doesnt update untill the very end. So after all my functions are finished, the progress bar goes from 0 to 100 instead of with steps.
loading.updateprogress()
script.install_requerement()
loading.updateprogress()
script.clone_vuestore_front()
loading.updateprogress()
How can I fix this?
EDIT: I tried to use threads in my code. I will post the whole script this time:
#!/usr/bin/python
import subprocess
import os
from threading import Thread
from tkinter import ttk
import tkinter as tk
import time
class Application(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.wm_geometry('700x400')
self.title('Install and integrate Vue Storefront')
self._frame = None
self.switch_frame(first_page)
def switch_frame(self, frame_class):
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.pack()
return self._frame
class loading(tk.Frame):
number=10
def __init__(self, master):
tk.Frame.__init__(self, master)
def t_create_progress_bar(self):
progress_bar = ttk.Progressbar(self, orient="horizontal", length=400)
progress_bar.pack()
progress_bar.after(1, self.t_loop_progress_bar, progress_bar)
self.mainloop()
def t_loop_progress_bar(self, progress_bar):
progress_bar["value"] = self.number
# Update it again in 100ms
progress_bar.after(100, self.t_loop_progress_bar, progress_bar)
class first_page(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
t = tk.Message(self, width=500,
text='first page')
t.pack()
tk.Button(self, text='Accept', command=lambda: \
self.AcceptClick(master)).pack(side=tk.RIGHT,
padx=5, pady=5)
def AcceptClick(self, master):
loadingclass = master.switch_frame(loading)
thread = Thread(target=loadingclass.t_create_progress_bar(), daemon=True)
thread.start()
loadingclass.number = 0 # 0% done
subprocess.run('sudo apt-get update', shell=True)
loadingclass.number = 25 # 25% done
subprocess.run('apt install nodejs', shell=True)
loadingclass.number = 50 # 50% done
subprocess.run('sudo apt-get update', shell=True)
loadingclass.number = 75 # 75% done
if __name__ == '__main__':
app = Application()
app.mainloop()
The frame does switch and I see the progress bar. But now the script runs the subproccesses after i close the window instead I want to run a function, then update the progress bar.
What did I do wrong?
Upvotes: 1
Views: 3357
Reputation: 36
As @TheLizzard suggested, try to change all local variables to static self vars. Also try to call root.update()
when you update progress bar value (after self.progressbar.step(...)
). Because root.mainloop()
, as far as I know, is sync, that's why if you call it after your sync code, progressbar is updated only after this, and if you call it before - It'll just stop the code below.
Upvotes: 1