Tkinter - 在文本小部件中记录文本 [英] Tkinter - logging text in Text Widget

查看:23
本文介绍了Tkinter - 在文本小部件中记录文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做一个能够在文本小部件中记录"文本的类.其他应用程序可以使用此类向文本小部件发送和显示日志.

I want to do a class that is able to "log" text in a Text Widget. This class could be used by other applications to send and display logs to the text widget.

class TraceConsole():

    def __init__(self):
        # Init the main GUI window
        self._logFrame = Tk.Frame()
        self._log      = Tk.Text(self._logFrame, wrap=Tk.NONE, setgrid=True)
        self._scrollb  = Tk.Scrollbar(self._logFrame, orient=Tk.VERTICAL)
        self._scrollb.config(command = self._log.yview) 
        self._log.config(yscrollcommand = self._scrollb.set)
        # Grid & Pack
        self._log.grid(column=0, row=0)
        self._scrollb.grid(column=1, row=0, sticky=Tk.S+Tk.N)
        self._logFrame.pack()


    def log(self, msg, level=None):
        # Write on GUI
        self._log.insert('end', msg + '\n')

    def exitWindow(self):
        # Exit the GUI window and close log file
        print('exit..')

用法示例:

t = TraceConsole()
t.log('hello world!')

我现在的问题是我不知道把主循环放在哪里.该记录器必须在后台"运行,并且在窗口关闭之前可以随时写入日志.

My problem now is that I don't know where to put the mainloop. This logger must run "in background" and it shall be possible to write log at any time until the window is closed.

推荐答案

我在这个问题上挣扎了一段时间,但最终还是采纳了这里的建议:

I struggled with this for a bit, but converged on the recommendations here:

wxPython:如何将 Python 的日志模块重定向到 TextCtrl

我在下面创建了一个示例,以阐明使用 Tkinter 登录到 GUI 控件的概念.下面的示例按您的要求记录到文本控件,但您可以通过将 MyHandlerText 类替换/复制为其他处理程序类(如 MyHandlerLabel),将日志消息发送到其他 GUI 组件,MyHandlerListbox 等(为处理程序类选择您自己的名称).然后,您将拥有一个处理各种感兴趣的 GUI 控件的处理程序.对我来说,最大的惊喜"时刻是 python.org 鼓励的模块级 getLogger 概念.

And I have an example below that I created to elucidate the concept of logging to a GUI control using Tkinter. The example below logs to a text control as you ask, but you can send log messages to other GUI components by replacing/copying the class MyHandlerText with other handler classes like MyHandlerLabel, MyHandlerListbox, etc. (choose your own names for the handler classes). Then you'd have a handler for a variety of GUI controls of interest. The big "a-ha" moment for me was the module-level getLogger concept encouraged by python.org.

import Tkinter
import logging
import datetime

# this item "module_logger" is visible only in this module,
# (but you can also reference this getLogger instance from other modules and other threads by passing the same argument name...allowing you to share and isolate loggers as desired)
# ...so it is module-level logging and it takes the name of this module (by using __name__)
# recommended per https://docs.python.org/2/library/logging.html
module_logger = logging.getLogger(__name__)

class simpleapp_tk(Tkinter.Tk):
    def __init__(self,parent):
        Tkinter.Tk.__init__(self,parent)
        self.parent = parent

        self.grid()

        self.mybutton = Tkinter.Button(self, text="ClickMe")
        self.mybutton.grid(column=0,row=0,sticky='EW')
        self.mybutton.bind("<ButtonRelease-1>", self.button_callback)

        self.mytext = Tkinter.Text(self, state="disabled")
        self.mytext.grid(column=0, row=1)

    def button_callback(self, event):
        now = datetime.datetime.now()
        module_logger.info(now)

class MyHandlerText(logging.StreamHandler):
    def __init__(self, textctrl):
        logging.StreamHandler.__init__(self) # initialize parent
        self.textctrl = textctrl

    def emit(self, record):
        msg = self.format(record)
        self.textctrl.config(state="normal")
        self.textctrl.insert("end", msg + "\n")
        self.flush()
        self.textctrl.config(state="disabled")

if __name__ == "__main__":

    # create Tk object instance
    app = simpleapp_tk(None)
    app.title('my application')

    # setup logging handlers using the Tk instance created above
    # the pattern below can be used in other threads...
    # ...to allow other thread to send msgs to the gui
    # in this example, we set up two handlers just for demonstration (you could add a fileHandler, etc)
    stderrHandler = logging.StreamHandler()  # no arguments => stderr
    module_logger.addHandler(stderrHandler)
    guiHandler = MyHandlerText(app.mytext)
    module_logger.addHandler(guiHandler)
    module_logger.setLevel(logging.INFO)
    module_logger.info("from main")    

    # start Tk
    app.mainloop()

这篇关于Tkinter - 在文本小部件中记录文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆