Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update a Tkinter text widget as it's written rather than after the class is finished

I'm in a bind, since this is being written on a classified machine I am unable to copy+paste here. Being somewhat a novice, my approach is probably unorthodox.

I have a GUI written in Tkinter with several buttons. Each button is linked to a class that, in effect, runs a short script. When the button is clicked, I inititalize a class log_window which is simply a Tkinter text widget. I then create a global variable linking log to the log_window I just created, and as the script runs I pipe sys.stdout/stderr to log (I created a write method specifically for this). Everything is kosher, except that the log_window text widget doesn't update with my piped stdout until after the class calling it is finished. However, if I simply print within the class, it will print in the order it is called.

Example

import Tkinter
from Tkinter import *
import time

class log_window:
    def __init__(self,master):
        self.textframe = Tkinter.Frame(master)
        self.text = Text(self.textframe)
        self.text.pack()
        self.textframe.pack()
    def write(self,text):
        self.text.insert(END,text)

class some_func1: # This effectively waits 5 seconds then prints both lines at once
    def __init__(self,master):
        log.write("some text")
        time.sleep(5)
        log.write("some text")

class some_func2: # This prints the first object, waits 5 seconds, then prints the second
    def __init__(self,master):
        print "some text"
        time.sleep(5)
        print "some text"

if __name__ == '__main__':
    global log    
    root = Tk()
    log = log_window(root)
    root.after(100,some_func1, root)
    root.after(100,some_func2, root)
    root.mainloop()

Sorry if my example is a little bit muffed, but I think it makes the point. The piping I do is through Popen and some system calls, but they aren't part of the issue, so I only highlighted what, I presume, is the LCD of the issue.

like image 712
Ryan Gibbons Avatar asked Jul 05 '11 19:07

Ryan Gibbons


People also ask

What does update () do in Tkinter?

Update method processes all the pending idle tasks, unvisited events, calling functions, and callbacks. The method is applicable for updating and processing all the events or tasks such as redrawing widgets, geometry management, configuring the widget property, etc.

Can you update a label in Tkinter?

Build A Paint Program With TKinter and PythonTo dynamically update the Label widget, we can use either config(**options) or an inline configuration method such as for updating the text, we can use Label["text"]=text; for removing the label widget, we can use pack_forget() method.

What is config () in Tkinter?

config() method. Syntax: Label.config(text) Parameter: text– The text to display in the label. This method is used for performing an overwriting over label widget.


1 Answers

I don't know the details of Tkinter's concurrency, but fiddling around reveals that if you put

master.update_idletasks()

after each call to log.write, it updates on cue. You could give log a .flush() method to do that (like file handles have), or you could just make log.write call it after writing.

like image 142
Thomas K Avatar answered Sep 23 '22 04:09

Thomas K