drew01886
drew01886

Reputation: 105

Scrolling Progress Bar in Tkinter

I have been trying to set up a progress bar in a python tkinter gui that shows that a process is running. The process is long and I have no way to really measure the progress, so I need to use an indeterminate progress bar. However, I really dislike the style of the ttk indeterminate progress bar that bounces back and forth. I want one that scrolls across the bar over and over again, kind of like this image

enter image description here

Is this possible with tkinter?

Upvotes: 3

Views: 5374

Answers (2)

Joules
Joules

Reputation: 580

I know its an old question, but I have found a way to do this for anyone else writing tkinter.

I've been working on a tkinter app for a bit now and have determined that to handle tkinter objects, you absolutely need a separate thread. Although it is apparently frowned upon to handle tkinter objects via something else than the mainloop() method, it has been working well for me. I've never had a main thread is not in main loop error and never experienced objects that didn't update correctly.

I edited Corey Goldberg's code a bit and got it working. Here's what I got (some explanations in the comments).

import tkinter
import tkinter.ttk as ttk
import threading

def mainProgram(): # secure the main program initialization in its own def
    root = tkinter.Tk()
    frame = ttk.Frame()
    # You need to use indeterminate mode to achieve this
    pb = ttk.Progressbar(frame, length=300, mode='indeterminate')
    frame.pack()
    pb.pack()

    # Create a thread for monitoring loading bar
    # Note the passing of the loading bar as an argument
    barThread = threading.Thread(target=keepLooping, args=(pb,))
    # set thread as daemon (thread will die if parent is killed)
    barThread.daemon=True
    # Start thread, could also use root.after(50, barThread.start()) if desired
    barThread.start()

    pb.start(25)
    root.mainloop()

def keepLooping(bar):
    # Runs thread continuously (till parent dies due to daemon or is killed manually)
    while 1:
        """
        Here's the tricky part.
        The loading bar's position (for any length) is between 0 and 100.
        Its position is calculated as position = value % 100.    
        Resetting bar['value'] to 0 causes it to return to position 0,
        but naturally the bar would keep incrementing forever till it dies.
        It works, but is a bit unnatural.
        """
        if bar['value']==100:
            bar.config(value=0) # could also set it as bar['value']=0    

if __name__=='__main__':
    mainProgram()    

I've added if __name__=='__main__': because I feel it defines the scope a bit better.

As a side note I've found that running threads with while 1: will crank my CPU at about 20-30% usage for that one thread in particular. It's easily solvable by importing time and using time.sleep(0.05) thereafter significantly lowering the CPU usage.

Tested on Win8.1, Python 3.5.0.

Upvotes: 0

Corey Goldberg
Corey Goldberg

Reputation: 60604

have you tried ttk's determinate Progressbar? You can make the progress just continuously scroll across the bar.

for example:

#!/usr/bin/env python3

import tkinter
import tkinter.ttk as ttk

root = tkinter.Tk()
frame = ttk.Frame()
pb = ttk.Progressbar(frame, length=300, mode='determinate')
frame.pack()
pb.pack()
pb.start(25)
root.mainloop()

Upvotes: 2

Related Questions