限制用作日志的ScrolledText内的行数

时间:2016-04-02 15:15:25

标签: python user-interface logging tkinter widget

我有一个ScrolledText小部件,我输出所有日志消息。由于有很多,而且这个程序运行了几个小时,它就会过载。

我需要一种限制行数的方法,比如400行。

我试图清除这样的文字:

self.mytext.delete(1.0, END)

但它没有做任何事情。

继承我的设置:

class XStatusFrame:

    def __init__(self, master, window):
        self.frame = Frame(master, relief="raised", width=950)
        self.frame.grid(row=4,column=0,sticky=(E,W),columnspan=20,rowspan=2)

        self.clear_btn = Button(self.frame,text="Clear Log", command=lambda: self.clear_log())
        self.clear_btn.pack(side=TOP, anchor=W)

        # text widget
        self.mytext = ScrolledText(self.frame, undo=True,state="disabled", fg="white", bg="black")
        #self.mytext = Text(self.frame, state="disabled", fg="white", bg="black")
        self.mytext.pack(fill=X)

        # Create textLogger
        text_handler = TextHandler(self.mytext)

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

    def clear_log(self):
        self.mytext.delete(1.0, END)



class TextHandler(logging.Handler):

    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 num_lines(self):
        return int(self.text.index('end').split('.')[0]) - 1

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

        # MY Try at limiting number of lines, which doesnt work...
        if self.num_lines() > 5:
            self.text.delete("1.0", END)

    def timestamp(self):
        ts = time.time()
        return datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')

2 个答案:

答案 0 :(得分:1)

这是一个日志显示的修改示例,我经常使用并减少它是相关的,应该(希望)有用。我删除了保存/打开日志文件的部分。如果您需要转储/保存日志文件,我也可以更新它的部分。我不熟悉logging所以我只是说明了在达到上限时删除文本内容。

from queue import Queue, Empty
import tkinter as tk
from tkinter import ttk, scrolledtext as stxt
import threading, time

MESSAGES = Queue()
UPPER_BOUND = 400

#Just to randomly have some data so you can see deleting etc
for i in range(10000):
    MESSAGES.put(i)

class Log(tk.Frame):

    def __init__(self, master):

        tk.Frame.__init__(self, master)
        self.log = stxt.ScrolledText(self, bg="black", fg="green2")
        self.log.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        thread = threading.Thread(target=self.update)
        thread.daemon = 1
        thread.start()

    def check_range(self):

        if float(self.log.index("end-1c")) == UPPER_BOUND:
            self.log.delete("1.0", "end-1c")
            #sleep to pause so you can see it did indeed delete
            time.sleep(5)

    def update(self):

        #I change states here since you typically want it to be read only
        try:
            self.log['state'] = 'normal'
            while True:
                self.check_range()
                data = MESSAGES.get_nowait()
                if not isinstance(data, str):
                    data = str(data)
                self.log.insert(tk.END, data+"\n")
                self.log.see(tk.END)
                self.update_idletasks()
        except Empty:
            self.log['state'] = 'disabled'
        self.after(100, self.update)

if __name__ == "__main__":

    root = tk.Tk()
    log = Log(root)
    log.pack(fill=tk.BOTH, side=tk.TOP, expand=1)
    root.mainloop()

或者,您可以使用位于here

的其他行计数方法

答案 1 :(得分:1)

在尝试删除行之前,需要将Text小部件的状态设置为normal,然后再次禁用它,就像添加行时一样。你的clear_log函数应该是:

def clear_log(self):
    self.mytext.configure(state='normal')
    self.mytext.delete(1.0, END)
    self.mytext.configure(state='disabled')