IIC2233 / syllabus-2020-1

Repositorio oficial del curso IIC2233 Programación Avanzada 🎉🎊
35 stars 68 forks source link

"WARNING: QApplication was not created in the main() thread." #1352

Closed sofiuni closed 4 years ago

sofiuni commented 4 years ago

Quiero que el cliente comienze despues de la interfaz ya que necesito que haya un QApplication creado para conectar las señales. Para lograr eso, creo un thread para la interfaz antes de empezar el thread del cliente. Esto falla, debido a que PyQt no me deja instanciar una ventana en un thread que no sea main(). Como puedo solucionar esto?

igbasly commented 4 years ago

Hola @sofiuni :v:

Efectivamente como mencionas, PyQt solo permite crear el QApplication y cualquier ventana dentro del thread principal, es decir, directamente el programa que se ejecuta y no de los programa paralelos que se crean (threads). La forma de enfrentar esta situación es mediante señales, una correcta combinación de ellas te permite crear y cerrar ventanas desde diferentes puntos o threads del programa. Me explico, una señal de forma general se puede ver como una acción dentro de tu programa, al gatillarse (hacer emit) esta desencadenará una serie de sucesos en su función de destino (manejador). Si consideras que las señales pueden viajar entre diferentes threads entonces se puede idear un flujo donde la señal desencadene una acción que permita abrir una ventana, de esta forma se puede ejecutar desde un thread distinto al principal.

Espero que esto aclare un poco la situación de que hacer para solucionar el problema y quedo atento en caso de más dudas, mucho éxito :raised_hands:.

sofiuni commented 4 years ago

El problema es que quiero conectar señales dentro de la clase del cliente, para enviar los datos de la interfaz, pero necesito crear la interfaz antes que el cliente para que funcione PyQt

sofiuni commented 4 years ago

No puedo usar señales por que para que corra el codigo tengo que instanciar primero el cliente, pero tiene que ser al reves

igbasly commented 4 years ago

Ok, creo entender un poco cómo estás modelando este flujo. Primero, tenemos que diferenciar entre instanciar y comenzar el proceso. Ya que son acciones diferentes que involucran distintos requisitos para su ejecución, lo cual puede ser el error que se está generando.

Para relacionar estos conceptos, hay que entender que las interfaces al final son threads, es decir, programas que funcionan en paralelo a otros y además probablemente tu cliente sea o contenga un thread para funcionar. Entonces, con estas dos cosas se puede permitir instanciar cualquiera de estas clase para realizar conexiones o cambios necesarios, y luego iniciar sus procesos en el orden que se estime conveniente mediante sus gatilladores show o run.

Un ejemplo claro de esto se puede ver en la AF04, donde es su archivo main se instancian todas las clases necesarias, luego se conectan las señales que estás utilizan y finalmente se comienzan los procesos (en el ejemplo se inicia la ventana con .show).

Ahora, si nos vamos a tu programa en particular, hay que analizar cuál se debe comenzar primero. Entonces como te mencionaba, no hay problemas con instanciar la ventana y/o el cliente, concertar sus señales y luego iniciar los proceso. De esta forma puedes intanciar todo sin necesariamente haber comenzado el programa, y después iniciar el cliente que mediante alguna señal inicie la ventana.

Creo que esto debería ayudarte a enfrentar un poco mejor el orden de las acciones a considerar 🙌, se todas formas hazme saber cualquier cosa que surja 👌.