5

I have created a tkinter GUI for my python script. When I run the script, I want a dynamic string in one of the Label widgets on the GUI window, which will display:

"Working." Then: "Working.." then "Working..."

and then start from "Working." again until the script is completed.

(Actually I'd prefer a progress bar in this area)

Is it possible?

alwbtc
  • 28,057
  • 62
  • 134
  • 188

2 Answers2

6

I wrote two simple scripts to help demonstrate how to do what you want. The first is using the label:

import tkinter as tk

root = tk.Tk()

status = tk.Label(root, text="Working")
status.grid()

def update_status():

    # Get the current message
    current_status = status["text"]

    # If the message is "Working...", start over with "Working"
    if current_status.endswith("..."): current_status = "Working"

    # If not, then just add a "." on the end
    else: current_status += "."

    # Update the message
    status["text"] = current_status

    # After 1 second, update the status
    root.after(1000, update_status)

# Launch the status message after 1 millisecond (when the window is loaded)
root.after(1, update_status)

root.mainloop()

The next one is using a progressbar:

import tkinter as tk

# You will need the ttk module for this
from tkinter import ttk

def update_status(step):

    # Step here is how much to increment the progressbar by.
    # It is in relation to the progressbar's length.
    # Since I made the length 100 and I am increasing by 10 each time,
    # there will be 10 times it increases before it restarts
    progress.step(step)

    # You can call 'update_status' whenever you want in your script
    # to increase the progressbar by whatever amount you want.
    root.after(1000, lambda: update_status(10))

root = tk.Tk()

progress = ttk.Progressbar(root, length=100)
progress.pack()

progress.after(1, lambda: update_status(10))

root.mainloop()

Note however that I couldn't do too much with the progressbar script because progressbars are a little tricky and need to be customized to your script exactly. I just wrote it to maybe shed a little light on the subject. The main part of my answer though is the label script.

  • In both examples, the call to `update()` is completely unnecessary, since you're immediately returning to the event loop. You also might want to use another word beside "recursion", since this doesn't fit the classical definition. Here, you don't have a function calling itself, it simply places a call on a queue to be called later, sometime after the function exits. – Bryan Oakley Aug 05 '13 at 02:09
2

Yes, it is possible. There are two ways to do it:

  1. Whenever you want to update the label from your code you can call the_widget.configure(the_text). This will change the text of the label.

  2. You can create an instance of a tkinter.StringVar, and assign it to the textvariable attribute of a label. Whenever you change the value of the variable (via the_variable.set(the_text), the label will automatically update.

Note that for either of these to work, the event loop needs to be able to process events (ie: you won't see anything if your function takes a long time to run and you never call update_idletasks or re-enter the event loop).

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • is it possible to run 2 processes at the same time? one of them will run the main script, and the other will keep altering the dynamic label string till the main script ends. – alwbtc Aug 05 '13 at 06:35
  • @alwbtc: yes, you can run two or more processes, or you can run two or more threads. The only caveat is that you can't configure widgets from any thread other than the main thread. There are several examples of how to do that on this site. – Bryan Oakley Aug 05 '13 at 10:36