JALE/jale/gui/output_log_frame.py
2024-11-28 10:52:57 +01:00

101 lines
3.2 KiB
Python

import logging
import tkinter
import customtkinter
class TextWidgetHandler(logging.Handler):
def __init__(self, text_widget):
super().__init__()
self.text_widget = text_widget
def emit(self, record):
"""
Emit a log record to the text widget.
"""
log_entry = self.format(record)
self.text_widget.update_log(log_entry)
class OutputLogFrame(customtkinter.CTkFrame):
def __init__(self, master, name):
"""
Creates a 2x1 frame with a text box for outputting log messages.
"""
super().__init__(master)
self.name = name
# configure grid layout (1x1)
self.rowconfigure(0, weight=0)
self.rowconfigure(1, weight=1) # log row will resize
self.columnconfigure(0, weight=1)
# Frame title
self.lbl_title = customtkinter.CTkLabel(
master=self,
text=f"{self.name}",
justify=tkinter.LEFT,
)
self.lbl_title.grid(row=0, column=0, sticky="wns", padx=15, pady=15)
# Text Box
self.txt_log = tkinter.Text(
master=self,
wrap=tkinter.WORD,
bg="#343638",
fg="#ffffff",
padx=20,
pady=5,
spacing1=4, # spacing before a line
spacing3=4, # spacing after a line / wrapped line
cursor="arrow",
font=("Courier", 14),
)
self.txt_log.grid(row=1, column=0, padx=(15, 0), pady=(0, 15), sticky="nsew")
self.txt_log.configure(state=tkinter.DISABLED)
# Scrollbar
self.scrollbar = customtkinter.CTkScrollbar(
master=self, command=self.txt_log.yview
)
self.scrollbar.grid(row=1, column=1, padx=(0, 15), pady=(0, 15), sticky="ns")
# Connect textbox scroll event to scrollbar
self.txt_log.configure(yscrollcommand=self.scrollbar.set)
self.controller = None
def set_controller(self, controller):
self.controller = controller
def update_log(self, msg, overwrite=False):
"""
Called from controller. Updates the log with given message. If overwrite is True,
the last line will be cleared before the message is added.
"""
self.txt_log.configure(state=tkinter.NORMAL)
if overwrite:
self.txt_log.delete("end-1c linestart", "end")
self.txt_log.insert(tkinter.END, "\n" + msg)
self.txt_log.configure(state=tkinter.DISABLED)
self.txt_log.see(tkinter.END)
def clear_log(self):
"""
Called from controller. Clears the log.
"""
self.txt_log.configure(state=tkinter.NORMAL)
self.txt_log.delete(1.0, tkinter.END)
self.txt_log.configure(state=tkinter.DISABLED)
self.txt_log.see(tkinter.END)
def set_logger(self, logger):
"""
Attaches the logger to this frame's text widget.
"""
self.logger = logger
handler = TextWidgetHandler(self)
handler.setFormatter(logging.Formatter("%(levelname)s - %(message)s"))
if len(logger.handlers) < 3:
self.logger.addHandler(handler)
self.logger.setLevel(logging.DEBUG) # Set the desired log level