2016-04-02 6 views
0

Ich habe ein ScrollledText-Widget, wo ich alle meine Protokollnachrichten ausgeben. Da es viel gibt und dieses Programm stundenlang läuft, wird es überlastet.Begrenzen der Anzahl der Zeilen in einem ScrollledText, der als Protokoll funktioniert

Ich brauche eine Möglichkeit, die Anzahl der Zeilen zu begrenzen, sagen wir zu 400 Zeilen.

Ich habe versucht, Text wie folgt zu löschen:

self.mytext.delete(1.0, END) 

Aber es tut nichts.

Heres mein Setup:

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

Antwort

1

Sie müssen den Zustand des Text-Widget, um normal zu setzen, bevor Sie versuchen, die Zeilen zu löschen, deaktivieren Sie es wieder, so wie du tun wenn Sie eine Zeile hinzufügen. Ihre Clear_log-Funktion sollte sein:

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

Hier ist ein modifiziertes Beispiel einer Protokollanzeige, die ich in der Regel relevant sein verwenden und fällten und sollte (hoffentlich) hilfreich sein. Ich habe die Teile zum Speichern/Öffnen von Protokolldateien gelöscht. Wenn Sie Protokolldateien dumpen/speichern müssen, kann ich auch mit den Teilen dafür aktualisieren. Ich bin nicht vertraut mit logging, also illustrierte ich einfach das Löschen des Textinhalts, wenn die obere Grenze erreicht ist.

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

Alternativ können Sie eine andere Linie Zählverfahren befindet verwenden here

Verwandte Themen