How To Redirecting "stdout" To A Label Widget?
Solution 1:
The reason you are not seeing the text set is that it is set correctly for a split second and then immediately set to blank. This is because print is sending a newline to stdout after the print statements. Here is a modified version that appends to the Label rather than overwrite it for every print statement.
classStdoutRedirector(IORedirector):
defwrite(self,str):
self.TEXT_INFO.config(text=self.TEXT_INFO.cget('text') + str)
Solution 2:
I made a class which copies stdout write calls to a tkinter widget be it a Label or a Text. Works for me on Python3.3.1/WindowsXp.:
import sys
classStdoutToWidget:
'''
Retrieves sys.stdout and show write calls also in a tkinter
widget. It accepts widgets which have a "text" config and defines
their width and height in characters. It also accepts Text widgets.
Use stop() to stop retrieving.
You can manage output height by using the keyword argument. By default
the class tries to get widget\'s height configuration and use that. If
that fails it sets self.height to None which you can also do manually.
In this case the output will not be trimmed. However if you do not
manage your widget, it can grow vertically hard by getting more and
more inputs.
'''# Inspired by Jesse Harris and Stathis# http://stackoverflow.com/a/10846997/2334951# http://stackoverflow.com/q/14710529/2334951# TODO: horizontal wrapping# make it a widget decorator (if possible)# height management for Text widget modedef__init__(self, widget, height='default', width='default'):
self._content = []
self.defstdout = sys.stdout
self.widget = widget
if height == 'default':
try:
self.height = widget.cget('height')
except:
self.height = Noneelse:
self.height = height
if width == 'default':
try:
self.width = widget.cget('width')
except:
self.width = Noneelse:
self.width = width
defflush(self):
'''
Frame sys.stdout's flush method.
'''
self.defstdout.flush()
defwrite(self, string, end=None):
'''
Frame sys.stdout's write method. This method puts the input
strings to the widget.
'''if string isnotNone:
self.defstdout.write(string)
try:
last_line_last_char = self._content[-1][-1]
except IndexError:
last_line_last_char = '\n'else:
if last_line_last_char == '\n':
self._content[-1] = self._content[-1][:-1]
if last_line_last_char != '\n'and string.startswith('\r'):
self._content[-1] = string[1:]
elif last_line_last_char != '\n':
self._content[-1] += string
elif last_line_last_char == '\n'and string.startswith('\r'):
self._content.append(string[1:])
else:
self._content.append(string)
ifhasattr(self.widget, 'insert') andhasattr(self.widget, 'see'):
self._write_to_textwidget()
else:
self._write_to_regularwidget(end)
def_write_to_regularwidget(self, end):
if self.height isNone:
self.widget.config(text='\n'.join(self.content))
else:
ifnot end:
content = '\n'.join(self.content[-self.height:])
else:
content = '\n'.join(self.content[-self.height+end:end])
self.widget.config(text=content)
def_write_to_textwidget(self):
self.widget.insert('end', '\n'.join(self.content))
self.widget.see('end')
defstart(self):
'''
Starts retrieving.
'''
sys.stdout = self
defstop(self):
'''
Stops retrieving.
'''
sys.stdout = self.defstdout
@propertydefcontent(self):
c = []
for li in self._content:
c.extend(li.split('\n'))
ifnot self.width:
return c
else:
result = []
for li in c:
whilelen(li) > self.width:
result.append(li[:self.width])
li = li[self.width:]
result.append(li)
return result
@content.setterdefcontent(self, string):
self._content = string.split('\n')
@propertydeferrors(self):
return self.defstdout.errors
@propertydefencoding(self):
return self.defstdout.encoding
EDIT1: I received a downvote, so here is the updated one. I use this in a Label widget and print() functions appear smoothly in my widget. Moreover as an extra feature if I pass None to the write call and let's say -1 as end argument, then it won't show last line (careful with indexing). I use this because I attached a slider to the widget. I will publish a demo soon.
Post a Comment for "How To Redirecting "stdout" To A Label Widget?"