2012-06-01 3 views
5

stdout을 Label 위젯으로 리디렉션하려고합니다. 목표는 내 스크립트에있는 모든 Python 인쇄물을 Label에 "인쇄"하는 것입니다."stdout"을 Label 위젯으로 리디렉션하는 방법은 무엇입니까?

from Tkinter import * 
import sys 
import tkMessageBox 


class App: 

    def __init__(self, master): 

     self.frame = Frame(master, borderwidth=5, relief=RIDGE) 
     self.frame.grid() 

     class IORedirector(object): 
      def __init__(self,TEXT_INFO): 
       self.TEXT_INFO = TEXT_INFO 

     class StdoutRedirector(IORedirector): 
      def write(self,str): 
       self.TEXT_INFO.config(text=str) 

     self.TEXT_HEADER = self.text_intro = Label(self.frame, bg="lightblue",text="MY SUPER PROGRAMM") ## HEADER TEXT 
     self.TEXT_HEADER.grid(row=0, column=0, columnspan=2, sticky=W+E+N+S) 

     self.MENU = Frame(self.frame, borderwidth=5, relief=RIDGE, height=12) 

     self.MENU.grid(row=1, column=0, sticky=N) 

     self.button = Button(self.MENU, text="QUIT", fg="red", bg="red", command=self.frame.quit) 
     self.button.grid(row=4, column=0) 

     self.BUTTON1 = Button(self.MENU, text="BUTTON1", command=self.BUTTON1_CMD) 
     self.BUTTON1.grid(row=0, column=0,sticky=W+E) 

     self.TEXT_INFO = Label(self.frame, height=12, width=40, text="I WANT TO SEE THE STDOUT OUTPUT HERE", bg="grey",borderwidth=5, relief=RIDGE) 
     self.TEXT_INFO.grid(row=1, column=1) 

     sys.stdout = StdoutRedirector(self.TEXT_INFO) 

    def BUTTON1_CMD(self): 
     print "TEST NUMBER ONE" 
     print "TEST NUMBER TWO" 


root = Tk() 
app = App(root) 
root.mainloop() 

답변

4

당신이 텍스트 세트가 표시되지 않는 이유는이 두 번째 분할에 대해 올바르게 설정되어 있는지입니다 :

하지만 BUTTON1 아무것도 클릭하면 발생은 ... 여기

내 코드입니다 즉시 빈 칸으로 설정하십시오. 이것은 print가 print 문 다음에 stdout으로 개행 문자를 보내는 것이기 때문입니다. 다음은 모든 인쇄 문에 대해 레이블을 덮어 쓰지 않고 레이블에 추가하는 수정 된 버전입니다.

class StdoutRedirector(IORedirector): 
     def write(self,str): 
      self.TEXT_INFO.config(text=self.TEXT_INFO.cget('text') + str) 
+1

당신은 최고입니다! 이것은 완벽하게 작동합니다! 도움을 주셔서 감사합니다, 나는 그 인쇄물이 print 문 다음에 stdout에 항상 개행 문자를 보내고 있다는 것을 몰랐습니다 ;-) (저는 15 개 이상의 평판이 없기 때문에 투표를 할 수 없습니다. 내가 가지고있는대로, 나는 당신을 위해 투표 할 것이다;)) –

3

레이블 또는 텍스트 인 tkinter 위젯에 stdout 쓰기 호출을 복사하는 클래스를 만들었습니다. Python3.3.1/지금 WindowsXP :

import sys 

class StdoutToWidget: 
    ''' 
    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 mode 

    def __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 = None 
     else: 
      self.height = height 
     if width == 'default': 
      try: 
       self.width = widget.cget('width') 
      except: 
       self.width = None 
     else: 
      self.width = width 

    def flush(self): 
     ''' 
     Frame sys.stdout's flush method. 
     ''' 
     self.defstdout.flush() 

    def write(self, string, end=None): 
     ''' 
     Frame sys.stdout's write method. This method puts the input 
     strings to the widget. 
     ''' 

     if string is not None: 
      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) 

     if hasattr(self.widget, 'insert') and hasattr(self.widget, 'see'): 
      self._write_to_textwidget() 
     else: 
      self._write_to_regularwidget(end) 

    def _write_to_regularwidget(self, end): 
     if self.height is None: 
      self.widget.config(text='\n'.join(self.content)) 
     else: 
      if not 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')   

    def start(self): 
     ''' 
     Starts retrieving. 
     ''' 
     sys.stdout = self 

    def stop(self): 
     ''' 
     Stops retrieving. 
     ''' 
     sys.stdout = self.defstdout 

    @property 
    def content(self): 
     c = [] 
     for li in self._content: 
      c.extend(li.split('\n')) 

     if not self.width: 
      return c 
     else: 
      result = [] 
      for li in c: 
       while len(li) > self.width: 
        result.append(li[:self.width]) 
        li = li[self.width:] 
       result.append(li) 
      return result 

    @content.setter 
    def content(self, string): 
     self._content = string.split('\n') 

    @property 
    def errors(self): 
     return self.defstdout.errors 

    @property 
    def encoding(self): 
     return self.defstdout.encoding 

EDIT1에 나를 위해 작동 : 내가 지금 여기에서, downvote을받은 업데이트입니다. 이것을 Label 위젯에 사용하고 print() 함수를 위젯에 부드럽게 나타냅니다. 또한 추가 기능으로 쓰기 호출에 None을 전달하고 끝 인수로 -1을 말하면 마지막 줄이 표시되지 않습니다 (인덱싱에주의하십시오). 위젯에 슬라이더를 연결했기 때문에 이것을 사용합니다. 나는 곧 데모를 발표 할 것이다.

관련 문제