Python登录到Tkinter Text Widget

23 python logging tkinter

有没有一个例子说明如何在Python中设置日志记录到Tkinter Text Widget?我已经看到这在几个应用程序中使用,但无法弄清楚如何将日志记录指向除日志文件之外的任何其他内容.

joh*_*han 11

除了上面的答案:尽管有很多建议的解决方案(在这里以及在另一个线程中),我自己也在努力做这项工作.最终我遇到了Moshe Kaplan的这个文本处理程序类,它使用了ScrolledText小部件(这可能比ScrollBar方法更容易).

我花了一些时间来弄清楚如何在线程应用程序中实际使用Moshe的类.最后,我创建了一个最小的演示脚本,演示如何使其全部工作.因为它可能对其他人有帮助,我将在下面分享.在我的具体情况,我想登录到这两个 GUI和文本文件; 如果您不需要,只需删除logging.basicConfig中的filename属性.

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()
Run Code Online (Sandbox Code Playgroud)

Github Gist链接到上面的代码:

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


ypr*_*rez 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')
Run Code Online (Sandbox Code Playgroud)


for*_*ord 7

我建立在Yuri的想法上,但需要做一些改变才能让事情发生变化:

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')
Run Code Online (Sandbox Code Playgroud)

请注意,必须将Text窗口状态从"正常"切换到"禁用"才能使窗口小部件成为只读状态.