Python Tkinter记录到ScrolledText和FileHandler

时间:2018-04-29 14:22:45

标签: python tkinter

在为我的一个命令行工具创建GUI的过程中,除了控制台或外部文件之外,还允许记录到Tkinter ScrolledText小部件。

我已经成功地从logging to a Tkinter text widget上的此线程调整了ScrolledText代码,并将日志返回到文件和GUI,但是当实时登录到控制台或文件时,ScrolledText小部件在main()函数返回之前,不会更新。当然,我也希望在Tkinter GUI中看到实时更新。

import argparse
import logging
from os.path import basename, splitext, join, isfile
import time
import Tkinter as tk
import ScrolledText

class TextHandler(logging.Handler):
    """This class allows you to log to a Tkinter Text or ScrolledText widget"""

    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 GUI(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.generate_button = tk.Button(self.root, text="Generate", command=main)
        self.quit_button = tk.Button(self.root, text="Quit", command=self.root.quit)
        self.text_handler = None
        self.build_gui()

    def build_gui(self):
        self.root.title('Logging test')
        self.generate_button.grid(row=0, column=0)
        self.quit_button.grid(row=0, column=1)

        # Add ScrolledText widget to display logging
        st = ScrolledText.ScrolledText()
        st.configure(font='TkFixedFont')
        st.grid(row=1, sticky='ew', columnspan=2)

        # Create textlogger
        self.text_handler = TextHandler(st)


################################################################################
# Main Program Flow
#
def main():
    # log something
    logger.info('something to log')
    time.sleep(1)
    logger.info('and something one second later')
    time.sleep(1)
    logger.info('and yet another second...')


################################################################################
# Read commandline arguments
#
def get_arguments():
    parser = argparse.ArgumentParser(
        description="Test GUI logging")
    parser.add_argument('--logdir', required=False, default=None)
    parser.add_argument('--debug', action="store_const", const=logging.DEBUG, default=logging.INFO)
    a = parser.parse_args()
    return a


################################################################################
# Configure logger
#
def get_logger(log_level=logging.INFO, log_dir=None, text_handler=None):
    script = splitext(basename(__file__))[0]
    logg = logging.getLogger(script)
    logg.setLevel(log_level)

    # set up file or stdout handlers
    if log_dir:
        info_file = join(log_dir, script + '.log')
        info_handler = logging.FileHandler(info_file)
    else:
        info_handler = logging.StreamHandler()

    # create formatter and add it to the handlers
    formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
    info_handler.setFormatter(formatter)
    info_handler.setLevel(log_level)
    if text_handler:
        text_handler.setFormatter(formatter)
        text_handler.setLevel(log_level)

    # add the handlers to logg
    logg.addHandler(info_handler)
    if text_handler:
        logg.addHandler(text_handler)

    return logg


################################################################################
# get args, configure logger and launch GUI
#
if __name__ == '__main__':
    args = get_arguments()
    root = tk.Tk()
    gui = GUI(root)
    logger = get_logger(log_level=args.debug, log_dir=args.logdir, text_handler=gui.text_handler)
    root.mainloop()

0 个答案:

没有答案