From 9957e6f766c6939e9a2aee62bd229b52be61f0c5 Mon Sep 17 00:00:00 2001 From: Dennis Eckerskorn Date: Thu, 5 Dec 2024 23:32:24 +0100 Subject: [PATCH] Implemented thread manager to handle threats and adjustes problem where the windows didnt open because of grpahics issue, also implemented graphics for cpu and ram usage --- .../processes_manager.cpython-313.pyc | Bin 0 -> 1666 bytes .../system_monitor.cpython-313.pyc | Bin 0 -> 4709 bytes .../__pycache__/tetris_game.cpython-313.pyc | Bin 0 -> 8611 bytes .../__pycache__/threaden_task.cpython-313.pyc | Bin 0 -> 1321 bytes .../threads_manager.cpython-313.pyc | Bin 0 -> 7836 bytes src/services/system_monitor.py | 157 ++++++++---------- src/services/threaden_task.py | 22 +++ src/services/threads_manager.py | 79 +++++++-- src/ui/__pycache__/__init__.cpython-313.pyc | Bin 0 -> 159 bytes .../centered_window.cpython-313.pyc | Bin 0 -> 11341 bytes src/ui/centered_window.py | 42 ++++- 11 files changed, 202 insertions(+), 98 deletions(-) create mode 100644 src/services/__pycache__/processes_manager.cpython-313.pyc create mode 100644 src/services/__pycache__/system_monitor.cpython-313.pyc create mode 100644 src/services/__pycache__/tetris_game.cpython-313.pyc create mode 100644 src/services/__pycache__/threaden_task.cpython-313.pyc create mode 100644 src/services/__pycache__/threads_manager.cpython-313.pyc create mode 100644 src/services/threaden_task.py create mode 100644 src/ui/__pycache__/__init__.cpython-313.pyc create mode 100644 src/ui/__pycache__/centered_window.cpython-313.pyc diff --git a/src/services/__pycache__/processes_manager.cpython-313.pyc b/src/services/__pycache__/processes_manager.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3b63b05ebee00b379cf757a697601a0937cd2809 GIT binary patch literal 1666 zcmZuyK~Eb;6rT02F*aZ?NHi`bFma(`g)yqCNUhaYB5k5dEeLtzsuGq)>t$>f?49k* zZb&#)J@gz!iptT)@-t}uKq#U_TcjSEOKzw>q)IP+7BCgrcB4m%bj36pTC zaCLVSNjHb8im8;pLCDG@v?UR}QHj&W8!#78HLuz6vXUP5MEBK1?3KJ*V==G;bzzkO_Ux`vCv&NgEoWU?S6)fO3CH^Ci z;w9m8qm1u69>d!doOZwk!%KxeTOrCY;9eb~F4Q^O7nJugGLup2)#tHmz!af1c!cA=CBQ~i3vRKJ99#NOeoO%JB4?w-r`-9ekMY|}yN zt|Twx4P!LSh@cMf@+%3Go6MtbnAxZGm`QC?Kh%2LNsl|OA5PwLT6BZ?_hkAWQJB8_ z(59a6FxN_t|Mw+o1d|5 zy2;rtv_aI?gO=~Cd0vHjtR}c!1MC9_3aIt#pn|lc55D9*3MZs^63Yo^foJGQC|&bP z5#lkJ@6hE`Hof>FH`_^{=8Ow{=3K|W=(w}oxp}6qzL=cr7^joVu>WKBN%rvJslIfs zubk*BKkc3A<(K;O^S4&c^wM7!Iow4`df{Sx^7&NZ*YS5Ra``SwUNOG}hTM}}XY5=r zp6Er0JWO?zL-DwMt}mSE3x8jZ0s4(7fvE3quH{i@8O-tcn6&xnJMXK8n=U(d)JkplArdY!nDT;w?R7%G?l w7hIlT5nggce#sGzejEw=l;46SoEJz;gSk`{MfnX)!tb?~R~G+7V0vNy00}FnO#lD@ literal 0 HcmV?d00001 diff --git a/src/services/__pycache__/system_monitor.cpython-313.pyc b/src/services/__pycache__/system_monitor.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce33be4bccec7c4852145e266b19592cb4a9cde2 GIT binary patch literal 4709 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 literal 0 HcmV?d00001 diff --git a/src/services/__pycache__/threaden_task.cpython-313.pyc b/src/services/__pycache__/threaden_task.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eb9c2f781e29609d5f505ea0e740c78185fbddfa GIT binary patch literal 1321 zcmZux%}X0W6rcS{{8$@5s+Rb*O{sLHc=KSDLa7L14Q zC2CV?lHv&2&7AO?j?u4Jm0sOBBSmPk#dF%8NQDT1d(xNJ#W z!3$Z4*sX?gIN`(2ar~+TZ0Dy~0uSo^8L@WZk zwzo@6Ilp`?M`>R3eb0BJR2b(zmLgTK%BDb9BU*8u6kiL*MRAFNpD4buo(CoNk_Tnx zgrc}stAyUOYPG!$dJj$9x*XU1zHwqb^E4-wP>?hHpM&wq;I1LD3Je zPtHfj57a~bd?b6Ie(7!C1DqzKs1tNe!`Ju7e3WJ6ECA%NxNt z@^;XYEO}l5!jR5bpaxd$kV1Ed0k(5ZlR;d?RZMmF@rv&`o^8~8W6P@qh7h_<2*~U64BJPMD2*mJrGD7Lg_( zEHo9~3p+l5FbE*<35H>C9W5gO(cpjl$6**F<^lG}MP{hJSKm7yn>tuJeDN#$;4C}y zBRlhL`uoyJ_7&Jx&-MQL>gUxned0u)IMt`F(xiW!XCV6aaV*10=QskN?JmG^Q(8T< z#|U=y7LNi>eTUp&Ty|ws+085gv&?5mGg7{s2U?K4gekQgcs|D;crxWNH8A#JP>lvU zxCyE;i4VaUsAGLbUue@Xexi?`>XTOr(MMw%I1Xpt?82G%?QI4#-$UtkP^wi> z*D3u_vn$P$45gbM7h%QonIBNf`|zUJD4qp~hAD*>g`Pw0Fy!7wEo6eyW0F*gyNXlH z5s(~#t^Y)>Wmy}$?$I>k&mC2pO1#m>l=)p)Vt;-gHSAo%LDyn($)`LAHv9_^!vI%` VBuPI>{{>n5s}4w0*90IA`v+#35d#1K literal 0 HcmV?d00001 diff --git a/src/services/__pycache__/threads_manager.cpython-313.pyc b/src/services/__pycache__/threads_manager.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8162fb8102745565fa30fd1c3399537442c5d84d GIT binary patch literal 7836 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 self.max_data_points: - config["data"].pop(0) - - self.update_graph(metric, config["data"]) - time.sleep(config["interval"]) - except Exception as e: - print(f"Error en update_metric ({metric}): {e}") +import psutil +import matplotlib.pyplot as plt +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg +import tkinter as tk +class SystemMonitor: + def __init__(self, parent_frame): + self.parent_frame = parent_frame + self.max_data_points = 60 + self.running = False + self.metrics = { + "CPU Usage": { + "data": [], + "fetch_func": psutil.cpu_percent, + "interval": 1 + }, + "RAM Usage": { + "data": [], + "fetch_func": lambda: psutil.virtual_memory().percent, + "interval": 1 + } + } + self.graphs = {} + self.init_graphs() - def update_graph(self, metric, data): - """Actualiza un gráfico con nuevos datos.""" - graph = self.graphs[metric] - x = list(range(len(data))) - graph["line"].set_data(x, data) - graph["axis"].set_xlim(0, len(data)) - graph["figure"].canvas.draw() + def init_graphs(self): + """Crea gráficos para todas las métricas.""" + for metric, config in self.metrics.items(): + fig, ax, line = self.create_graph(metric) + self.graphs[metric] = {"figure": fig, "axis": ax, "line": line} - def stop_threads(self): - """Detiene la ejecución de todos los hilos de monitoreo.""" - self.running = False + def create_graph(self, title): + """Crea un gráfico para una métrica específica.""" + frame = tk.Frame(self.parent_frame) + frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) + + label = tk.Label(frame, text=title, font=("Arial", 14, "bold")) + label.pack() + + fig, ax = plt.subplots(figsize=(5, 3)) + ax.set_title(title) + ax.set_xlabel("Time") + ax.set_ylabel("Usage (%)") + ax.set_ylim(0, 100) + line, = ax.plot([], [], lw=2) + + canvas = FigureCanvasTkAgg(fig, frame) + canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True) + + return fig, ax, line + + def update_metric(self, metric): + """Actualiza los datos de una métrica específica.""" + config = self.metrics[metric] + try: + new_data = config["fetch_func"]() + config["data"].append(new_data) + + if len(config["data"]) > self.max_data_points: + config["data"].pop(0) + + self.update_graph(metric, config["data"]) + except Exception as e: + print(f"Error en update_metric ({metric}): {e}") + + def update_graph(self, metric, data): + """Actualiza un gráfico con nuevos datos.""" + graph = self.graphs[metric] + x = list(range(len(data))) + + def redraw(): + graph["line"].set_data(x, data) + graph["axis"].set_xlim(0, len(data)) + graph["figure"].canvas.draw() + + self.parent_frame.after(0, redraw) \ No newline at end of file diff --git a/src/services/threaden_task.py b/src/services/threaden_task.py new file mode 100644 index 0000000..30c88d3 --- /dev/null +++ b/src/services/threaden_task.py @@ -0,0 +1,22 @@ +import threading + +"""Clase que se encarga de manjear hilos. Permite arrancar y parar un hilo""" + +class ThreadenTask: + def __init__(self): + self.running = False + self.thread = None + + + def start(self, target, *args): + """Inicia un hilo con el objetivo especificado.""" + if not self.running: + self.running = True + self.thread = threading.Thread(target=target, args=args, daemon=True) + self.thread.start() + + def stop(self): + """Detiene el hilo""" + self.running = False + if self.thread: + self.thread.join() \ No newline at end of file diff --git a/src/services/threads_manager.py b/src/services/threads_manager.py index e3dcaa1..0035300 100644 --- a/src/services/threads_manager.py +++ b/src/services/threads_manager.py @@ -1,35 +1,86 @@ -import threading import datetime import time import requests import random +from services.threaden_task import ThreadenTask +from services.system_monitor import SystemMonitor + class ThreadsManager: + """Constructor""" def __init__(self, ui_instance): self.ui_instance = ui_instance + self.system_monitor = None + self.tasks = { + "time": ThreadenTask(), + "temperature": ThreadenTask(), + "emails":ThreadenTask(), + } + self.system_monitor_tasks = {} + + + + def set_system_monitor(self, system_monitor): + """Asigna el monitor del sistema y crea sus tareas""" + self.system_monitor = system_monitor + for metric in system_monitor.metrics.keys(): + self.system_monitor_tasks[metric] = ThreadenTask() + + def start_threads(self): - # Hilo para actualizar el reloj - threading.Thread(target=self.update_time, daemon=True).start() + """Se inician los hilos, Tiempo, Temperatura, Emails""" + self.tasks["time"].start(self.update_time) + self.tasks["temperature"].start(self.update_temperature) + self.tasks["emails"].start(self.update_emails) - # Hilo para actualizar la temperatura - threading.Thread(target=self.update_temperature, daemon=True).start() + if self.system_monitor: + for metric in self.system_monitor.metrics.keys(): + self.system_monitor_tasks[metric].start( + self.update_system_metric, + metric + ) - # Hilo para actualizar correos (simulado) - threading.Thread(target=self.update_emails, daemon=True).start() + + def stop_threads(self): + """Recorre tasks y para los hilos""" + for task in self.tasks.values(): + task.stop() + + for task in self.system_monitor_tasks.values(): + task.stop() + + if self.system_monitor: + self.system_monitor.running = False + + + + def update_system_metric(self, metric): + """Actualiza una métrica específica del monitor del sistema.""" + while self.system_monitor_tasks[metric].running: + try: + self.system_monitor.update_metric(metric) + time.sleep(self.system_monitor.metrics[metric]["interval"]) + except Exception as e: + print(f"Error updating metric {metric}: {e}") + + + def update_time(self): - while True: + while self.tasks["time"].running: current_time = datetime.datetime.now().strftime('%H:%M:%S') current_date = datetime.datetime.now().strftime('%d/%m/%Y') self.ui_instance.after(0, lambda: self.ui_instance.info_labels["hora"].configure(text=f"Hora: {current_time}")) self.ui_instance.after(0, lambda: self.ui_instance.info_labels["fecha"].configure(text=f"Fecha: {current_date}")) time.sleep(1) + + def update_temperature(self): API_KEY = "4ba2b87d7fa32934530b5b4a5a83ebf7" # Reemplaza con tu clave de OpenWeatherMap CITY = "Madrid" # Cambia por tu ciudad - while True: + while self.tasks["temperature"].running: try: temperature = self.get_real_temperature(API_KEY, CITY) if temperature is not None: @@ -41,6 +92,8 @@ class ThreadsManager: print(f"Error al obtener la temperatura: {e}") time.sleep(600) # Actualiza cada 10 minutos + + def get_real_temperature(self, api_key, city): url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric" response = requests.get(url) @@ -50,13 +103,17 @@ class ThreadsManager: else: print(f"Error al obtener la temperatura: {response.status_code}") return None + + def update_emails(self): count = 0 - while True: + while self.tasks["emails"].running: count += random.randint(0, 2) # Simula la llegada de 0-2 correos self.ui_instance.after( 0, lambda: self.ui_instance.info_labels["emails"].configure(text=f"Correos sin leer: {count}") ) - time.sleep(10) # Actualiza cada 10 segundos + time.sleep(20) # Actualiza cada 10 segundos + + diff --git a/src/ui/__pycache__/__init__.cpython-313.pyc b/src/ui/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ca5c9ae15dffa62df04319902512490a3fffac86 GIT binary patch literal 159 zcmey&%ge<81j~{G(n0iN5CH>>P{wB#AY&>+I)f&o-%5reCLr%KNa~hdvQUS@GjSg><`N@_q+epYI7NpXyCX--L|V?jYsYC(QXaZz$iX=Y4(d}dx|NqoFs iLFFwDo80`A(wtPgB37VrAnS@jjE~HWjEqIhKo$T{KqtNc literal 0 HcmV?d00001 diff --git a/src/ui/__pycache__/centered_window.cpython-313.pyc b/src/ui/__pycache__/centered_window.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3bdf8ae999aed4bb23819042842aa726119bb059 GIT binary patch literal 11341 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 ac74NuRqCkC;-407pZ)0U|1cP)&Hf)pLu1_l literal 0 HcmV?d00001 diff --git a/src/ui/centered_window.py b/src/ui/centered_window.py index 5aca4fc..315dd4f 100644 --- a/src/ui/centered_window.py +++ b/src/ui/centered_window.py @@ -8,18 +8,19 @@ import threading from services.threads_manager import ThreadsManager from services.processes_manager import ProcessManager from services.tetris_game import TetrisGame +from services.system_monitor import SystemMonitor class CenteredWindow(ctk.CTk): def __init__(self, title="MultiApp", width_percentage=0.8, height_percentage=0.8): # Inicializacion de la clase: super().__init__() - - # Titulo de la ventana: self.title(title) + # Inicializar managers (orden es importante) self.thread_manager = ThreadsManager(self) self.process_manager = ProcessManager() + self.system_monitor = None # Obtener la resolucion de la pantalla: screen_width = self.winfo_screenwidth() @@ -38,6 +39,8 @@ class CenteredWindow(ctk.CTk): #Configura la ventana self.configure_window() + self.protocol("WM_DELETE_WINDOW", self.on_close) + def configure_window(self): # Configuracion de la ventana: self.configure(bg_color="lightgray") @@ -45,8 +48,18 @@ class CenteredWindow(ctk.CTk): self.create_right_panel() self.create_center_panel() self.create_bottom_bar() + self.thread_manager.start_threads() + + + def on_close(self): + """Maneja el cierre de la ventana""" + self.thread_manager.stop_threads() + self.destroy() + + + def create_left_panel(self): # Panel izquierdo left_panel = ctk.CTkFrame(self, width=200) @@ -70,6 +83,8 @@ class CenteredWindow(ctk.CTk): btn = ctk.CTkButton(left_panel, text=text, command=command, width=150) btn.pack(pady=5, padx=10) + + def create_center_panel(self): # Panel central con pestañas center_panel = ctk.CTkFrame(self) @@ -82,7 +97,18 @@ class CenteredWindow(ctk.CTk): for tab_name in ["Resultados Scrapping", "Navegador", "Correos", "Juego", "Sistema"]: tab = tab_view.add(tab_name) - if tab_name == "Juego": + if tab_name == "Sistema": + # Crear un frame para los gráficos del sistema + system_frame = ctk.CTkFrame(tab) + system_frame.pack(fill=ctk.BOTH, expand=True, padx=5, pady=5) + + # Inicializar SystemMonitor con el frame de la pestaña + self.system_monitor = SystemMonitor(system_frame) + + # Asignar el system_monitor al thread_manager + self.thread_manager.set_system_monitor(self.system_monitor) + + elif tab_name == "Juego": # Crear un marco intermedio para centrar game_frame = ctk.CTkFrame(tab) game_frame.pack(expand=True) @@ -109,16 +135,22 @@ class CenteredWindow(ctk.CTk): label = ctk.CTkLabel(tab, text=f"Contenido de {tab_name}", font=("Arial", 12)) label.pack(pady=10) + + def start_tetris_game(self): """Método para iniciar el juego.""" if not self.tetris_game.running: self.tetris_game.running = True self.tetris_game.update_game() + + def pause_tetris_game(self): """Método para pausar el juego.""" self.tetris_game.running = False + + def restart_tetris_game(self): """Método para reiniciar el juego.""" self.tetris_game.reset_game() @@ -153,6 +185,8 @@ class CenteredWindow(ctk.CTk): ) student_info.pack(anchor=ctk.W, padx=10) + + def create_bottom_bar(self): # Crear la barra inferior self.bottom_bar = ctk.CTkFrame(self, fg_color="lightblue", height=40) @@ -170,5 +204,7 @@ class CenteredWindow(ctk.CTk): for label in self.info_labels.values(): label.pack(side=ctk.LEFT, padx=10, pady=5) + + def dummy_action(self): print("Acción no implementada") \ No newline at end of file