2012-11-10 26 views
18

PythonでTkinter Text Widgetへのログインを設定する例はありますか?私はこれがいくつかのアプリで使われているのを見たことがありますが、ログファイル以外のものにログを送る方法を理解することはできません。Python Tkinter Textウィジェットへのログ

答えて

9

あなたはlogging.Handlerのサブクラスを作成する必要があり、例えば:私はユーリのアイデアに構築されたが、いくつかの変更を行うために必要な

import logging 
from Tkinter import INSERT 

class WidgetLogger(logging.Handler): 
    def __init__(self, widget): 
     logging.Handler.__init__(self) 
     self.widget = widget 

    def emit(self, record): 
     # Append message (record) to the widget 
     self.widget.insert(INSERT, record + '\n') 
6

が働いて物事を取得するには、次の状態をバックトグルすることを

import logging 
import Tkinter as tk 

class WidgetLogger(logging.Handler): 
    def __init__(self, widget): 
     logging.Handler.__init__(self) 
     self.setLevel(logging.INFO) 
     self.widget = widget 
     self.widget.config(state='disabled') 

    def emit(self, record): 
     self.widget.config(state='normal') 
     # Append message (record) to the widget 
     self.widget.insert(tk.END, self.format(record) + '\n') 
     self.widget.see(tk.END) # Scroll to the bottom 
     self.widget.config(state='disabled') 

注意をし、 Textウィジェットを読み取り専用にするには、 'normal'から 'disabled'に変更する必要があります。

1

さらにfordの答えをビルドします。ここでは、スクロールするTextウィジェットがあります。 logging_handlerメンバーがあなたのロガーに追加したものです。

import logging 
from Tkinter import END, N, S, E, W, Scrollbar, Text 
import ttk 

class LoggingHandlerFrame(ttk.Frame): 

    class Handler(logging.Handler): 
     def __init__(self, widget): 
      logging.Handler.__init__(self) 
      self.setFormatter(logging.Formatter("%(asctime)s: %(message)s")) 
      self.widget = widget 
      self.widget.config(state='disabled') 

     def emit(self, record): 
      self.widget.config(state='normal') 
      self.widget.insert(END, self.format(record) + "\n") 
      self.widget.see(END) 
      self.widget.config(state='disabled') 

    def __init__(self, *args, **kwargs): 
     ttk.Frame.__init__(self, *args, **kwargs) 

     self.columnconfigure(0, weight=1) 
     self.columnconfigure(1, weight=0) 
     self.rowconfigure(0, weight=1) 

     self.scrollbar = Scrollbar(self) 
     self.scrollbar.grid(row=0, column=1, sticky=(N,S,E)) 

     self.text = Text(self, yscrollcommand=self.scrollbar.set) 
     self.text.grid(row=0, column=0, sticky=(N,S,E,W)) 

     self.scrollbar.config(command=self.text.yview) 

     self.logging_handler = LoggingHandlerFrame.Handler(self.text) 
0

fordでもビルドされていますが、色付きのテキストを追加してください!上記の回答に加えて

class WidgetLogger(logging.Handler): 
    def __init__(self, widget): 
     logging.Handler.__init__(self) 
     self.setLevel(logging.DEBUG) 
     self.widget = widget 
     self.widget.config(state='disabled') 
     self.widget.tag_config("INFO", foreground="black") 
     self.widget.tag_config("DEBUG", foreground="grey") 
     self.widget.tag_config("WARNING", foreground="orange") 
     self.widget.tag_config("ERROR", foreground="red") 
     self.widget.tag_config("CRITICAL", foreground="red", underline=1) 

     self.red = self.widget.tag_configure("red", foreground="red") 
    def emit(self, record): 
     self.widget.config(state='normal') 
     # Append message (record) to the widget 
     self.widget.insert(tk.END, self.format(record) + '\n', record.levelname) 
     self.widget.see(tk.END) # Scroll to the bottom 
     self.widget.config(state='disabled') 
     self.widget.update() # Refresh the widget 
5

:このために提案されたソリューション(ここともthis other thread中)がたくさんあるにもかかわらず、私は、これは自分自身を動作させるためにかなり苦労しました。最終的に私はthis text handler class by Moshe Kaplanに遭遇しました。これはScrolledTextウィジェットを使用しています(おそらくScrollBarメソッドよりも簡単です)。

スレッドアプリケーションでMosheのクラスを実際に使用する方法を理解するまでには時間がかかりました。最後に、すべてを動作させる方法を示す最小デモスクリプトを作成しました。それは他の人に役立つかもしれないので、私はそれを以下に共有しています。私の特別なケースでは、にGUIとテキストファイルの両方であるにログしたかったのです。必要がない場合は、というファイル名の属性をlogging.basicConfigに削除してください。ここで上記のコードに

import time 
import threading 
import logging 
try: 
    import tkinter as tk # Python 3.x 
    import tkinter.scrolledtext as ScrolledText 
except ImportError: 
    import Tkinter as tk # Python 2.x 
    import ScrolledText 

class TextHandler(logging.Handler): 
    # This class allows you to log to a Tkinter Text or ScrolledText widget 
    # Adapted from Moshe Kaplan: https://gist.github.com/moshekaplan/c425f861de7bbf28ef06 

    def __init__(self, text): 
     # run the regular Handler __init__ 
     logging.Handler.__init__(self) 
     # Store a reference to the Text it will log to 
     self.text = text 

    def emit(self, record): 
     msg = self.format(record) 
     def append(): 
      self.text.configure(state='normal') 
      self.text.insert(tk.END, msg + '\n') 
      self.text.configure(state='disabled') 
      # Autoscroll to the bottom 
      self.text.yview(tk.END) 
     # This is necessary because we can't modify the Text from other threads 
     self.text.after(0, append) 

class myGUI(tk.Frame): 

    # This class defines the graphical user interface 

    def __init__(self, parent, *args, **kwargs): 
     tk.Frame.__init__(self, parent, *args, **kwargs) 
     self.root = parent 
     self.build_gui() 

    def build_gui(self):      
     # Build GUI 
     self.root.title('TEST') 
     self.root.option_add('*tearOff', 'FALSE') 
     self.grid(column=0, row=0, sticky='ew') 
     self.grid_columnconfigure(0, weight=1, uniform='a') 
     self.grid_columnconfigure(1, weight=1, uniform='a') 
     self.grid_columnconfigure(2, weight=1, uniform='a') 
     self.grid_columnconfigure(3, weight=1, uniform='a') 

     # Add text widget to display logging info 
     st = ScrolledText.ScrolledText(self, state='disabled') 
     st.configure(font='TkFixedFont') 
     st.grid(column=0, row=1, sticky='w', columnspan=4) 

     # Create textLogger 
     text_handler = TextHandler(st) 

     # Logging configuration 
     logging.basicConfig(filename='test.log', 
      level=logging.INFO, 
      format='%(asctime)s - %(levelname)s - %(message)s')   

     # Add the handler to logger 
     logger = logging.getLogger()   
     logger.addHandler(text_handler) 

def worker(): 
    # Skeleton worker function, runs in separate thread (see below) 
    while True: 
     # Report time/date at 2-second intervals 
     time.sleep(2) 
     timeStr = time.asctime() 
     msg = 'Current time: ' + timeStr 
     logging.info(msg) 

def main(): 

    root = tk.Tk() 
    myGUI(root) 

    t1 = threading.Thread(target=worker, args=[]) 
    t1.start() 

    root.mainloop() 
    t1.join() 

main() 

Githubの要点リンク:あなたは** `TclStackFree取得の方のため

https://gist.github.com/bitsgalore/901d0abe4b874b483df3ddc4168754aa

+0

:間違ったfreePtr' **エラーを、上記の答えはこれを解決します。 'self.widget.after(0、function_to_execute)'を使うとウィジェットがそれが属するスレッドによって修正されます。 – Felix

関連する問題