Gibt es da draußen ein Beispiel, wie man die Anmeldung in Python an einem Tkinter Text Widget einrichtet? Ich habe gesehen, dass dies in mehreren Apps verwendet wurde, aber ich kann nicht herausfinden, wie ich die Protokollierung auf etwas anderes als eine Protokolldatei lenken soll.Python Logging to Tkinter Text Widget
Antwort
Sie sollten logging.Handler
Unterklasse, zB:
import logging
from Tkinter import INSERT
class WidgetLogger(logging.Handler):
def __init__(self, widget):
logging.Handler.__init__(self)
self.widget = widget
def emit(self, record):
# Append message (record) to the widget
self.widget.insert(INSERT, record + '\n')
ich auf Yuris Idee gebaut, aber brauchte ein paar Änderungen, um die Dinge zum Laufen zu bringen:
import logging
import Tkinter as tk
class WidgetLogger(logging.Handler):
def __init__(self, widget):
logging.Handler.__init__(self)
self.setLevel(logging.INFO)
self.widget = widget
self.widget.config(state='disabled')
def emit(self, record):
self.widget.config(state='normal')
# Append message (record) to the widget
self.widget.insert(tk.END, self.format(record) + '\n')
self.widget.see(tk.END) # Scroll to the bottom
self.widget.config(state='disabled')
Beachten Sie, dass der Zustand zurück Makeln und von "normal" zu "deaktiviert" ist erforderlich, um das Widget schreibgeschützt zu machen.
Aufbauend auf ford's Antwort, hier ist ein Scroll-Text-Widget, das das Protokoll schwänzt. Das Mitglied logging_handler
ist, was Sie Ihrem Logger hinzufügen.
import logging
from Tkinter import END, N, S, E, W, Scrollbar, Text
import ttk
class LoggingHandlerFrame(ttk.Frame):
class Handler(logging.Handler):
def __init__(self, widget):
logging.Handler.__init__(self)
self.setFormatter(logging.Formatter("%(asctime)s: %(message)s"))
self.widget = widget
self.widget.config(state='disabled')
def emit(self, record):
self.widget.config(state='normal')
self.widget.insert(END, self.format(record) + "\n")
self.widget.see(END)
self.widget.config(state='disabled')
def __init__(self, *args, **kwargs):
ttk.Frame.__init__(self, *args, **kwargs)
self.columnconfigure(0, weight=1)
self.columnconfigure(1, weight=0)
self.rowconfigure(0, weight=1)
self.scrollbar = Scrollbar(self)
self.scrollbar.grid(row=0, column=1, sticky=(N,S,E))
self.text = Text(self, yscrollcommand=self.scrollbar.set)
self.text.grid(row=0, column=0, sticky=(N,S,E,W))
self.scrollbar.config(command=self.text.yview)
self.logging_handler = LoggingHandlerFrame.Handler(self.text)
Auch auf Ford bauen, aber farbigen Text hinzufügen!
class WidgetLogger(logging.Handler):
def __init__(self, widget):
logging.Handler.__init__(self)
self.setLevel(logging.DEBUG)
self.widget = widget
self.widget.config(state='disabled')
self.widget.tag_config("INFO", foreground="black")
self.widget.tag_config("DEBUG", foreground="grey")
self.widget.tag_config("WARNING", foreground="orange")
self.widget.tag_config("ERROR", foreground="red")
self.widget.tag_config("CRITICAL", foreground="red", underline=1)
self.red = self.widget.tag_configure("red", foreground="red")
def emit(self, record):
self.widget.config(state='normal')
# Append message (record) to the widget
self.widget.insert(tk.END, self.format(record) + '\n', record.levelname)
self.widget.see(tk.END) # Scroll to the bottom
self.widget.config(state='disabled')
self.widget.update() # Refresh the widget
Zusätzlich zu den oben genannten Antworten: Auch wenn viele der vorgeschlagenen Lösungen für diese gibt es (hier und auch in this other thread), war ich ziemlich viel kämpfen, dies selbst arbeiten. Schließlich lief ich in this text handler class by Moshe Kaplan, die ein ScrolledText Widget verwendet (das ist wahrscheinlich einfacher als die ScrollBar-Methode).
Es hat einige Zeit gedauert, bis ich herausgefunden habe, wie man Moshes Klasse tatsächlich in einer Thread-Anwendung verwendet. Am Ende habe ich ein minimales Demo-Skript erstellt, das zeigt, wie alles funktioniert. Wie es für andere hilfreich sein könnte, teile ich es unten. In meinem speziellen Fall wollte ich auf sowohl die GUI und eine Textdatei protokollieren; Wenn Sie das nicht benötigen, entfernen Sie einfach den Dateinamen Attribut in logging.basicConfig.
import time
import threading
import logging
try:
import tkinter as tk # Python 3.x
import tkinter.scrolledtext as ScrolledText
except ImportError:
import Tkinter as tk # Python 2.x
import ScrolledText
class TextHandler(logging.Handler):
# This class allows you to log to a Tkinter Text or ScrolledText widget
# Adapted from Moshe Kaplan: https://gist.github.com/moshekaplan/c425f861de7bbf28ef06
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 myGUI(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.build_gui()
def build_gui(self):
# Build GUI
self.root.title('TEST')
self.root.option_add('*tearOff', 'FALSE')
self.grid(column=0, row=0, sticky='ew')
self.grid_columnconfigure(0, weight=1, uniform='a')
self.grid_columnconfigure(1, weight=1, uniform='a')
self.grid_columnconfigure(2, weight=1, uniform='a')
self.grid_columnconfigure(3, weight=1, uniform='a')
# Add text widget to display logging info
st = ScrolledText.ScrolledText(self, state='disabled')
st.configure(font='TkFixedFont')
st.grid(column=0, row=1, sticky='w', columnspan=4)
# Create textLogger
text_handler = TextHandler(st)
# Logging configuration
logging.basicConfig(filename='test.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s')
# Add the handler to logger
logger = logging.getLogger()
logger.addHandler(text_handler)
def worker():
# Skeleton worker function, runs in separate thread (see below)
while True:
# Report time/date at 2-second intervals
time.sleep(2)
timeStr = time.asctime()
msg = 'Current time: ' + timeStr
logging.info(msg)
def main():
root = tk.Tk()
myGUI(root)
t1 = threading.Thread(target=worker, args=[])
t1.start()
root.mainloop()
t1.join()
main()
Github Gist Link oben Code hier:
https://gist.github.com/bitsgalore/901d0abe4b874b483df3ddc4168754aa
- 1. tkinter Text Widget typeError
- 2. Python tkinter Eingabe Widget Verwendung
- 3. Hyperlink in Tkinter Text Widget?
- 4. Tkinter Text widget: Konfigurieren Schrift
- 5. Text im Tkinter Label-Widget unterstreichen?
- 6. tkinter Überprüfen Sie, ob Text-Widget leer
- 7. Tkinter focus_set() funktioniert nicht auf Text-Widget
- 8. redirect stdout zu tkinter Text widget
- 9. Einstellung Bildlaufleiste in Tkinter Baum Widget Python
- 10. Tkinter Text Widget wird nicht gefüllt/erweitern
- 11. Tkinter: Syntax-Hervorhebung für Text-Widget
- 12. Tkinter Text widget: Fetching Cursor Auswahl
- 13. Tkinter Label-Widget unter Eintrag Widget
- 14. tkinter Widget nicht angezeigt
- 15. Notebook-Widget in Tkinter
- 16. So markieren Sie Text in einem tkinter Text-Widget
- 17. Tkinter Scale Widget Status
- 18. Widget-Werte in tkinter erhalten
- 19. Tkinter Text-Widget: Suchen Sie nach etwas außerhalb einer Liste
- 20. Treeview Tkinter Widget - klickbare Links
- 21. Clipping-Text in Python/Tkinter
- 22. Warum "verzögert" Tkinter-Text-Widget für erhöhte Fensterhöhen?
- 23. Make Tkinter Widget Fokus nehmen
- 24. Subclassing Tkinter ein eigenes Widget
- 25. Die Gesamtanzahl der Zeilen in einem Tkinter Text-Widget abrufen?
- 26. Aktualisieren Sie ein Tkinter Text Widget in Echtzeit?
- 27. erweiterte Funktionen hinzufügen zu einem tkinter Text-Widget
- 28. Aktualisieren Eintrag Widget mit Text von der Bildschirmtastatur in tkinter
- 29. Python anhängen tkinter Widget zur Liste zeigt als int-Wert
- 30. Python Tkinter Eintrag Widget wird keine Eingabe akzeptieren
Für diejenigen von Ihnen, die ** 'TclStackFree bekommen: falsche freePtr' ** Fehler, die Antwort oben löst dieses Problem. Die Verwendung von 'self.widget.after (0, function_to_execute)' stellt sicher, dass das Widget von dem Thread geändert wird, zu dem es gehört. – Felix