Я пробовал разные способы, но у меня это не сработало, я разместил несколько отпечатков, чтобы лучше определить, где возникла ошибка, и оказалось, что она остается по адресу: [Ventana3] Finalizando hilo...
вот мой код:
import tkinter as tk
from tkinter import ttk
import cv2
from threading import Thread
from ultralytics import YOLO
from PIL import Image, ImageTk
from tkinter import messagebox
import numpy as np
from threading import Event
Model = YOLO("Modelo_v5m.pt")
class Ventana3:
def __init__(self, master, cam_indices, on_regresar):
print("[Ventana3] Inicializando...")
self.root = master
self.on_regresar = lambda: self.before_on_regresar(on_regresar)
self.selected_cameras_indices = cam_indices
self.stop_event = Event()
self.setup_window3()
def setup_window3(self):
print("[Ventana3] Configurando ventana...")
self.root.title("Visualización de Cámaras")
self.root.geometry("880x700")
self.camera_frames = []
self.root.protocol("WM_DELETE_WINDOW", self.on_close_window)
# Crear un frame principal para usar pack
main_frame = tk.Frame(self.root)
main_frame.pack(fill=tk.BOTH, expand=True)
# Iniciar captura de video para las cámaras seleccionadas
self.cap = [cv2.VideoCapture(i) for i in self.selected_cameras_indices]
for i, cap in enumerate(self.cap):
print(f"[Ventana3] Cap {i} iniciado: {cap.isOpened()}")
# Cálculo dinámico de columnas y tamaño de frames
num_camaras = len(self.cap)
cols = round(num_camaras ** 0.5)
rows = (num_camaras // cols) + (num_camaras % cols > 0)
for i in range(num_camaras):
camera_frame = tk.Label(main_frame)
camera_frame.grid(row=i // cols, column=i % cols, sticky='nsew')
main_frame.grid_columnconfigure(i % cols, weight=1)
main_frame.grid_rowconfigure(i // cols, weight=1)
self.camera_frames.append(camera_frame)
ttk.Button(self.root, text="Regresar", width=20, command=self.on_regresar).place(x=15, y=15) #boton regresar a la ventana 2
self.stop_event.clear()
# Iniciar el proceso de actualización de las cámaras en un hilo separado
print("[Ventana3] Iniciando hilo de captura de video...")
self.thread = Thread(target=self.start_camera_streams)
self.thread.daemon = True
self.thread.start()
def before_on_regresar(self, on_regresar):
print("[Ventana3] Botón Regresar presionado, iniciando limpieza...")
self.clear_window()
on_regresar()
def start_camera_streams(self):
print("[Ventana3] Captura de video iniciada.")
while not self.stop_event.is_set():
for i, cap in enumerate(self.cap):
ret, frame = cap.read()
if ret:
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # Convertir el frame de BGR (OpenCV) a RGB
resultados = Model.predict(frame_rgb) # Procesar el frame con el modelo
anotaciones = resultados[0].plot() # YOLOv8 espera una lista de imágenes
img = Image.fromarray(anotaciones)
photo = ImageTk.PhotoImage(image=img)
self.update_camera_frame(i, photo)
print("Captura de video detenida.")
def update_camera_frame(self, index, photo):
if index < len(self.camera_frames):
camera_frame = self.camera_frames[index]
if camera_frame.winfo_exists(): # Comprueba si el widget aún existe
camera_frame.configure(image=photo)
camera_frame.image = photo
def clear_window(self):
print("[Ventana3] Deteniendo hilo y liberando cámaras...")
self.stop_event.set() # Indica al hilo que debe detenerse
self.root.after(100, self.final_cleanup)
def final_cleanup(self): # Detener el hilo de actualización de la cámara
print("[Ventana3] Finalizando hilo...")
if hasattr(self, 'thread'):
self.thread.join()
print("[Ventana3] Hilo finalizado.")
print("[Ventana3] Liberando cámaras...")
if hasattr(self, 'cap'): # Comprueba si self.cap tiene cámaras abiertas para liberar
for i, cap in enumerate(self.cap):
cap.release()
print(f"[Ventana3] Cámara {i} liberada.")
print("[Ventana3] Limpiando widgets...")
for widget in self.root.winfo_children(): # Limpiar los widgets de la ventana
widget.destroy()
print("[Ventana3] Limpieza de widgets finalizada.")
def on_close_window(self):
print("[Ventana3] Cerrando ventana...")
self.clear_window()
self.root.destroy()
Кроме того, код моего main.py, где я управляю действиями кнопок:
import tkinter as tk
from Ventana1 import Ventana1
from Ventana2 import Ventana2
from Ventana3 import Ventana3
class MainApp:
def __init__(self, root):
# Initialize the MainApp class with the root tkinter window
self.root = root
self.current_window = None
self.goto_window1()
def clear_window(self):
# Remove all widgets from the root window
for widget in self.root.winfo_children():
widget.destroy()
def goto_window1(self):
# Clear the current window and go to Ventana1
self.clear_window()
self.current_window = Ventana1(self.root, lambda: self.navigate("Ventana2"))
def goto_window2(self):
# Clear the current window and go to Ventana2
self.clear_window()
self.current_window = Ventana2(self.root, self.navigate)
#manejar acciones de los botones
def navigate(self, action, cam_indices=None):
if action == "CONFIRMAR": # Solo navega a la ventana 3 si hay cámaras seleccionadas
self.goto_window3(cam_indices)
elif action == "REGRESAR":
self.goto_window1()
elif action == "Ventana2":
self.goto_window2()
elif action == "Ventana3":
self.goto_window3()
def goto_window2_from_window3(self): #llamar a clear_window para limpiar recursos de Ventana3
if self.current_window and hasattr(self.current_window, 'clear_window'):
self.current_window.clear_window()
self.goto_window2()
def goto_window3(self, cam_indices=None):
# Clear the current window and go to Ventana3
self.clear_window()
self.current_window = Ventana3(self.root, cam_indices, self.goto_window2_from_window3)
def end_app(self):
# Close the root window and end the application
self.root.destroy()
if __name__ == "__main__":
# Create the root tkinter window
root = tk.Tk()
# Create an instance of the MainApp class
app = MainApp(root)
# Start the tkinter event loop
root.mainloop()
Я попробовал несколько вещей, и я надеюсь, что потоки камеры закрываются правильно, и когда я нажимаю кнопку возврата, я перехожу в окно 2
Я пробовал разные способы, но у меня это не сработало, я разместил несколько отпечатков, чтобы лучше определить, где возникла ошибка, и оказалось, что она остается по адресу: [Ventana3] Finalizando hilo... вот мой код: [code]import tkinter as tk from tkinter import ttk import cv2 from threading import Thread from ultralytics import YOLO from PIL import Image, ImageTk from tkinter import messagebox import numpy as np from threading import Event
# Crear un frame principal para usar pack main_frame = tk.Frame(self.root) main_frame.pack(fill=tk.BOTH, expand=True)
# Iniciar captura de video para las cámaras seleccionadas self.cap = [cv2.VideoCapture(i) for i in self.selected_cameras_indices]
for i, cap in enumerate(self.cap): print(f"[Ventana3] Cap {i} iniciado: {cap.isOpened()}")
# Cálculo dinámico de columnas y tamaño de frames num_camaras = len(self.cap) cols = round(num_camaras ** 0.5) rows = (num_camaras // cols) + (num_camaras % cols > 0)
for i in range(num_camaras): camera_frame = tk.Label(main_frame) camera_frame.grid(row=i // cols, column=i % cols, sticky='nsew') main_frame.grid_columnconfigure(i % cols, weight=1) main_frame.grid_rowconfigure(i // cols, weight=1) self.camera_frames.append(camera_frame)
ttk.Button(self.root, text="Regresar", width=20, command=self.on_regresar).place(x=15, y=15) #boton regresar a la ventana 2
self.stop_event.clear()
# Iniciar el proceso de actualización de las cámaras en un hilo separado print("[Ventana3] Iniciando hilo de captura de video...") self.thread = Thread(target=self.start_camera_streams) self.thread.daemon = True self.thread.start()
def start_camera_streams(self): print("[Ventana3] Captura de video iniciada.") while not self.stop_event.is_set(): for i, cap in enumerate(self.cap): ret, frame = cap.read() if ret: frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # Convertir el frame de BGR (OpenCV) a RGB resultados = Model.predict(frame_rgb) # Procesar el frame con el modelo anotaciones = resultados[0].plot() # YOLOv8 espera una lista de imágenes img = Image.fromarray(anotaciones) photo = ImageTk.PhotoImage(image=img) self.update_camera_frame(i, photo) print("Captura de video detenida.")
def update_camera_frame(self, index, photo): if index < len(self.camera_frames): camera_frame = self.camera_frames[index] if camera_frame.winfo_exists(): # Comprueba si el widget aún existe camera_frame.configure(image=photo) camera_frame.image = photo
def clear_window(self): print("[Ventana3] Deteniendo hilo y liberando cámaras...") self.stop_event.set() # Indica al hilo que debe detenerse self.root.after(100, self.final_cleanup)
def final_cleanup(self): # Detener el hilo de actualización de la cámara print("[Ventana3] Finalizando hilo...") if hasattr(self, 'thread'): self.thread.join() print("[Ventana3] Hilo finalizado.")
print("[Ventana3] Liberando cámaras...") if hasattr(self, 'cap'): # Comprueba si self.cap tiene cámaras abiertas para liberar for i, cap in enumerate(self.cap): cap.release() print(f"[Ventana3] Cámara {i} liberada.")
print("[Ventana3] Limpiando widgets...") for widget in self.root.winfo_children(): # Limpiar los widgets de la ventana widget.destroy() print("[Ventana3] Limpieza de widgets finalizada.")
def on_close_window(self): print("[Ventana3] Cerrando ventana...") self.clear_window() self.root.destroy() [/code] Кроме того, код моего main.py, где я управляю действиями кнопок: [code]import tkinter as tk from Ventana1 import Ventana1 from Ventana2 import Ventana2 from Ventana3 import Ventana3
class MainApp: def __init__(self, root): # Initialize the MainApp class with the root tkinter window self.root = root self.current_window = None self.goto_window1()
def clear_window(self): # Remove all widgets from the root window for widget in self.root.winfo_children(): widget.destroy()
def goto_window1(self): # Clear the current window and go to Ventana1 self.clear_window() self.current_window = Ventana1(self.root, lambda: self.navigate("Ventana2"))
def goto_window2(self): # Clear the current window and go to Ventana2 self.clear_window() self.current_window = Ventana2(self.root, self.navigate)
#manejar acciones de los botones def navigate(self, action, cam_indices=None): if action == "CONFIRMAR": # Solo navega a la ventana 3 si hay cámaras seleccionadas self.goto_window3(cam_indices) elif action == "REGRESAR": self.goto_window1() elif action == "Ventana2": self.goto_window2() elif action == "Ventana3": self.goto_window3()
def goto_window2_from_window3(self): #llamar a clear_window para limpiar recursos de Ventana3 if self.current_window and hasattr(self.current_window, 'clear_window'): self.current_window.clear_window() self.goto_window2()
def goto_window3(self, cam_indices=None): # Clear the current window and go to Ventana3 self.clear_window() self.current_window = Ventana3(self.root, cam_indices, self.goto_window2_from_window3)
def end_app(self): # Close the root window and end the application self.root.destroy()
if __name__ == "__main__": # Create the root tkinter window root = tk.Tk() # Create an instance of the MainApp class app = MainApp(root) # Start the tkinter event loop root.mainloop() [/code] Я попробовал несколько вещей, и я надеюсь, что потоки камеры закрываются правильно, и когда я нажимаю кнопку возврата, я перехожу в окно 2
Я создал графический тест. Окно Tkinter вылетает, когда я нажимаю кнопку множественного выбора в викторине на вычитание. Он не вылетает ни на одном другом типе викторин. Иногда это срабатывает, когда я нажимаю кнопку с множественным выбором, только...
I have form and I connected with MySQL, so whenever i fill up it will be shown in mySQL. The next step is to have a table of contents in my index.php, what i have. But now when I wanna press delete button it shows me blanket page.
Я пытаюсь войти в систему, это мой php-код, но ничего не возвращается, когда я нажимаю «Отправить», даже если я ввожу правильный пароль, поэтому пароль _verify не работает в моем браузере или я ввожу неверный код. Я потратил 3 дня, чтобы решить...