2012-06-01 11 views
5

stdoutをLabelウィジェットにリダイレクトしようとしています。目標は、スクリプトにあるすべてのPythonプリントをLabelに「印刷」することです。"stdout"をラベルウィジェットにリダイレクトする方法は?

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に私の作品:私は、更新1であるので、ここでは、downvoteを受けました。これをLabelウィジェットで使用し、print()関数をウィジェット内にスムーズに表示します。さらに、書き込みコールにNoneを渡し、最後の引数として-1とすると、最後の行は表示されません(索引付けには注意してください)。ウィジェットにスライダーをつけているので、これを使用します。私はすぐにデモを公開します。

関連する問題