How to Redirect Print Statements to Tkinter Text Widget

How to redirect print statements to Tkinter text widget

You can probably solve this by replacing sys.stdout with your own file-like object that writes to the text widget.

For example:

import Tkinter as tk
import sys

class ExampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
toolbar = tk.Frame(self)
toolbar.pack(side="top", fill="x")
b1 = tk.Button(self, text="print to stdout", command=self.print_stdout)
b2 = tk.Button(self, text="print to stderr", command=self.print_stderr)
b1.pack(in_=toolbar, side="left")
b2.pack(in_=toolbar, side="left")
self.text = tk.Text(self, wrap="word")
self.text.pack(side="top", fill="both", expand=True)
self.text.tag_configure("stderr", foreground="#b22222")

sys.stdout = TextRedirector(self.text, "stdout")
sys.stderr = TextRedirector(self.text, "stderr")

def print_stdout(self):
'''Illustrate that using 'print' writes to stdout'''
print "this is stdout"

def print_stderr(self):
'''Illustrate that we can write directly to stderr'''
sys.stderr.write("this is stderr\n")

class TextRedirector(object):
def __init__(self, widget, tag="stdout"):
self.widget = widget
self.tag = tag

def write(self, str):
self.widget.configure(state="normal")
self.widget.insert("end", str, (self.tag,))
self.widget.configure(state="disabled")

app = ExampleApp()
app.mainloop()

How to redirect stdout to a Tkinter Text widget

The problem is that when you call app.mainloop(), the thread is busy executing the Tkinter mainloop, so the statements before it are not executed until you exit the loop. But once you exit the mainloop, you try to use the Text widget but it is already destroyed.

I recommend you to move the call to main to the callback of a Tkinter widget (I suppose you are already trying to do that with app.button_press()), so the Text object can be used to display the text.

class CoreGUI(object):
def __init__(self,parent):
self.parent = parent
self.InitUI()
button = Button(self.parent, text="Start", command=self.main)
button.grid(column=0, row=1, columnspan=2)

def main(self):
print('whatever')

def InitUI(self):
self.text_box = Text(self.parent, wrap='word', height = 11, width=50)
self.text_box.grid(column=0, row=0, columnspan = 2, sticky='NSWE', padx=5, pady=5)
sys.stdout = StdoutRedirector(self.text_box)

root = Tk()
gui = CoreGUI(root)
root.mainloop()

redirect stdout to tkinter text widget

The fix is simple: don't create more than one redirector. The whole point of the redirector is that you create it once, and then normal print statements will show up in that window.

You'll need to make a couple of small changes to your redirector function. First, it shouldn't call Tk; instead, it should create an instance of Toplevel since a tkinter program must have exactly one root window. Second, you must pass a text widget to IORedirector since it needs to know the exact widget to write to.

def redirector(inputStr=""):
import sys
root = Toplevel()
T = Text(root)
sys.stdout = StdoutRedirector(T)
T.pack()
T.insert(END, inputStr)

Next, you should only call this function a single time. From then on, to have data appear in the window you would use a normal print statement.

You can create it in the main block of code:

win = Tk()
...
r = redirector()
win.mainloop()

Next, you need to modify the write function, since it must write to the text widget:

class StdoutRedirector(IORedirector):
'''A class for redirecting stdout to this Text widget.'''
def write(self,str):
self.text_area.insert("end", str)

Finally, change your Zerok function to use print statements:

def Zerok():
...
if os.stat(filename).st_size==0:

print(filename)
else:
print("There are no empty files in that Directory")
break

How to redirect in real time STDOUT from imported module to Tkinter Text Widget in python?

Call sleepBtn.update_idletasks() before each time.sleep(2) command. Otherwise the view will not be updated before the end of the sleep procedure.

Print all outputs (in realtime) in text widget in Tkinter

Change your RedirectText write function to update the widget after writing to it.

class RedirectText(object):
def __init__(self, text_widget):
"""Constructor"""
self.output = text_widget

def write(self, string):
"""Add text to the end and scroll to the end"""
self.output.insert('end', string)
self.output.see('end')
self.output.update_idletasks()

Redirect intput and output to Tkinter text widget

Is there a similar method of having the text widget able to take display the input prompts, take in the input, and display the output?

No, there is no way to automatically use the text widget as stdin. You'll have to write code to detect a carriage return and then grab the data from the beginning of the prompt to the end of the line.

stdout to tkinter GUI

You need to make a file-like class whose write method writes to the Tkinter widget instead, and then do sys.stdout = <your new class>. See this question.

Example (copied from the link):

class IORedirector(object):
'''A general class for redirecting I/O to this Text widget.'''
def __init__(self,text_area):
self.text_area = text_area

class StdoutRedirector(IORedirector):
'''A class for redirecting stdout to this Text widget.'''
def write(self,str):
self.text_area.write(str,False)

and then, in your Tkinter widget:

# To start redirecting stdout:
import sys
sys.stdout = StdoutRedirector( self )
# (where self refers to the widget)

# To stop redirecting stdout:
sys.stdout = sys.__stdout__


Related Topics



Leave a reply



Submit