Search code examples
pythontkinterlabeltransparency

Progressbar with Percentage Label?


How can I put a label in the middle of a progressbar that shows the percentage? The problem is that python doesn't support transparency for label backgrounds, so I don't know how I can solve that.


Solution

  • This is possible using a ttk.Style. The idea is to modify the layout of the Horizontal.TProgressbar style (do the same with Vertical.TProgressbar for a vertical progressbar) to add a label inside the bar:

    Usual Horizontal.TProgressbar layout:

    [('Horizontal.Progressbar.trough',
      {'children': [('Horizontal.Progressbar.pbar',
         {'side': 'left', 'sticky': 'ns'})],
       'sticky': 'nswe'})]
    

    With an additional label:

    [('Horizontal.Progressbar.trough',
      {'children': [('Horizontal.Progressbar.pbar',
         {'side': 'left', 'sticky': 'ns'})],
       'sticky': 'nswe'}),
     ('Horizontal.Progressbar.label', {'sticky': 'nswe'})]
    

    Then, the text of the label can be changed with style.configure.

    Here is the code:

    import tkinter as tk
    from tkinter import ttk
    
    root = tk.Tk()
    
    style = ttk.Style(root)
    # add label in the layout
    style.layout('text.Horizontal.TProgressbar', 
                 [('Horizontal.Progressbar.trough',
                   {'children': [('Horizontal.Progressbar.pbar',
                                  {'side': 'left', 'sticky': 'ns'})],
                    'sticky': 'nswe'}), 
                  ('Horizontal.Progressbar.label', {'sticky': 'nswe'})])
    # set initial text
    style.configure('text.Horizontal.TProgressbar', text='0 %', anchor='center')
    # create progressbar
    variable = tk.DoubleVar(root)
    pbar = ttk.Progressbar(root, style='text.Horizontal.TProgressbar', variable=variable)
    pbar.pack()
    
    def increment():
        pbar.step()  # increment progressbar 
        style.configure('text.Horizontal.TProgressbar', 
                        text='{:g} %'.format(variable.get()))  # update label
        root.after(200, increment)
        
    increment()
    
    root.mainloop()
    

    screenshot of the result

    Styling

    The font, color and position of the label can be changed using style.configure. For instance,

    style.configure('text.Horizontal.TProgressbar', foreground="red", 
                    font='Arial 20', anchor='w')
    

    gives screenshot of result

    Multiple progressbars

    The text is set through the style therefore to have multiple progressbars with different labels, one needs to use a different style for each. However, there is no need to set the layout for each style: create the layout 'text.Horizontal.TProgressbar' like in the above code and then use substyles 'pb1.text.Horizontal.TProgressbar', 'pb2.text.Horizontal.TProgressbar', ... for each progressbar. Then the text of a single progressbar can be changed with

    style.configure('pb1.text.Horizontal.TProgressbar', text=...)