I want to create a large text upon Tkinter
menu command and provide visual support by a progress bar. Although the progress bar is meant to start before the subsequent time-consuming loop, the progress bar shows up only after the large text was created and displayed.
def menu_bar(self):
self.create_menu.add_command(label="Create large file",
command=self.create_large_file)
def create_large_file(self):
self.progressbar = ttk.Progressbar(self.master, mode='indeterminate')
self.progressbar.pack()
self.progressbar.start()
self.text.delete(1.0, 'end')
self.file_content = []
i = 0
while i < 2000000:
line = lfd.input_string
self.file_content.append(line + "\n")
i += 1
self.file_content = ''.join(self.file_content)
self.text.insert(1.0, self.file_content)
Introduction to the Tkinter Progressbar widget A Progressbar widget allows you to give feedback to the user about the progress of a long-running task. To create a Progressbar widget, you use the ttk.Progressbar class: ttk.Progressbar(container, **options)
The progress bar doesn't have a feature to display text on its own. We can do this using a Label widget. All we have to do is to place a Label widget where ever we want to implement the text. Now we can configure the text value of the label & can change it with the change in the Python Tkinter progress bar.
I think the problem is that the time-consuming loop is preventing the tkinter
event loop, mainloop()
, from running. In other words, when your work intensive function runs in the same thread as the GUI, it interferes with it by hogging the interpreter.
To prevent this you can use a secondary Thread to run your function and run the GUI and its progressbar in the main thread. To give you an idea of how to do this, here's a simple example I derived from code in another (unrelated) progressbar question to show how easily something like that can be done. Note: It's generally recommended that secondary threads not be given direct access to the main thread's tkinter
objects.
from Tkinter import *
import ttk
import time
import threading
def foo():
time.sleep(5) # simulate some work
def start_foo_thread(event):
global foo_thread
foo_thread = threading.Thread(target=foo)
foo_thread.daemon = True
progressbar.start()
foo_thread.start()
root.after(20, check_foo_thread)
def check_foo_thread():
if foo_thread.is_alive():
root.after(20, check_foo_thread)
else:
progressbar.stop()
root = Tk()
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
progressbar = ttk.Progressbar(mainframe, mode='indeterminate')
progressbar.grid(column=1, row=100, sticky=W)
ttk.Button(mainframe, text="Check",
command=lambda:start_foo_thread(None)).grid(column=1, row=200,
sticky=E)
for child in mainframe.winfo_children():
child.grid_configure(padx=5, pady=5)
root.bind('<Return>', start_foo_thread)
root.mainloop()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With