Tkinter语言 - 在文本小部件中记录文本



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

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!')

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

我为此挣扎了一会儿,但最终还是采纳了以下建议:

  • Python日志工具

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

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

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()

在这种情况下,您已经创建了一个将在应用程序中使用的组件。主循环将在该应用程序中被调用,它们将写入您的日志小部件。

您可以在TraceConsole的相同python文件中添加一些简单的使用示例(例如您给出的示例)和/或测试,使用类似

的内容
if __name__ == '__main__':
    m = tkinter.Tk()
    t = TraceConsole()
    t.log('hello world!')
    m.mainloop()

我通常这样做,这样我可以在将tkinter组件合并到我的应用程序之前单独测试它。

相关内容

  • 没有找到相关文章

最新更新