IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PyQt Python Discussion :

Plusieurs Qthreads et mise à jour de l'interface graphique ?


Sujet :

PyQt Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 61
    Par défaut Plusieurs Qthreads et mise à jour de l'interface graphique ?
    Bonjour à tous,
    je suis assez novice en PyQt mais je suis sur un projet assez complexe.
    J'ai créé une interface graphique et j'ai quelques soucis de freeze de l'écran.

    Mon projet consiste à utiliser des capteurs de pression pour relever des poids.

    Le poids est relevé toutes les 400ms et met à jour des champs texte de mon interface graphique.
    Tout cela est géré dans le Thread principal, jusque là pas de soucis. J'utilise les librairies du constructeur (Phidgets).

    Le problème c'est que je veux analyser ces relevés de poids en continu et faire certaines actions en fonction de ces données récoltées. Alors j'ai créé un Qthread avec une boucle infinie pour cela.
    Tout fonctionne bien sauf que pendant ce temps, l'interface graphique est complètement gelée, pourtant un qthread permet bien de faire tourner un code en arrière plan non?
    J'ai essayé d'incorporer des processEvents() à différents endroits dans la boucle infinie, mais rien y fait.

    Si vous avez quelques idées, je suis preneur!
    Merci beaucoup d'avance

  2. #2
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Salut,

    Les process (ou threads) autres que la boucle événementielle de l'application ne doivent pas la figer.

    C'est pour cela qu'on les utilisent d'ailleurs.

    En suçant mon pouce je pense que le problème vient de ton code.

  3. #3
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Si j'ai bien compris le problème, voilà comment je coderais la synchro entre le thread principal et le QThread:

    - Le QThread a un fonctionnement permanent. Il attend (boucle while) une info à traiter en questionnant une pile (QQueue protégée par un QMutex) et exécute le traitement quand la pile n'est plus vide. Une fois le traitement terminé, et le résultat envoyé, il attend de nouveau une nouvelle info dans la pile.

    - Quand le thread principal a une info à traiter, il la met dans la pile (ce qui va déclencher le traitement par le QThread).

    - Quand le QThread a terminé le traitement, il envoie le résultat avec un signal (emit) créé spécialement pour ça.

    - Ce signal est reçu par le thread principal et la méthode prévue (connect) est exécutée pour exploiter le résultat, par exemple pour l'afficher dans un widget.

    Cela parait compliqué, mais ça garantit que entre le thread principal et le Qthread, aucun n'attend l'autre, ce qui évite le gel du graphique.

    Et il faut toujours se rappeler que le QThread (les threads en général) ne doit pas toucher directement au graphique.

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 61
    Par défaut
    Merci pour vos contributions.
    Désolé du retard, j'attendais une notification par mail lorsqu'une réponse était postée mais celle ci n'était pas activée.
    Mon thread principal est dédié à mon interface graphique: les contrôles, les actions des contrôles etc.
    Mais dans ce thread principal il y a aussi la réception des données relevées par mes capteurs de pression (12 au total) qui mettent à jour des QtextEdit avec les valeurs relevées toutes les 400ms. Tout cela fonctionne.

    Ce que je souhaite faire dans un second thread lancé par un bouton: c'est d'analyser les données en continu, via une boucle infinie.... Je vais chercher les valeurs des 12 Qtextedit, je calcule des sommes, écart type etc. et en fonction des résultats j'effectue certaines actions. mais une fois tout cela terminé, je recommence à analyser ces données jusqu'à ce que j'appuie sur un second bouton, le soucis c'est que lorsque ce second thread est activé, mon interface freeze complètement, pourtant, je vois dans ma console python que selon les résultats des analyses effectuées, les variations de poids de mes capteurs de pression sont bien prises en compte mais tout reste figé dans mes 12 qtextedit, malgré un app.processEvents() dans la boucle.

    Ci dessous, le code simplifé de mon second thread:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    class Calcul(QtCore.QThread):
     
    	def __init__(self):
    		QtCore.QThread.__init__(self)
     
    	def __del__(self):
    		self.wait()
     
    	def run(self):
    		while True:
    			combinaison_trouvee = 1
    			nbPesonsStables = 12
    			items = []
    			data = []
    			for id_peson in range(1,13):
    				if int(ui.MainPage_GroupPesons.findChild(QtGui.QLineEdit,"MainPage_Poids" + str(id_peson)).text()) == 0:
    					if nbPesonsStables == 11:
    						combinaison_trouvee = 0
    						break
    					else:
    						nbPesonsStables -=1
     
    				else: # Si la valeur du peson est > 0 alors on integre les valeurs dans les tableaux
    					items.append(id_peson)
    					data.append(int(ui.MainPage_GroupPesons.findChild(QtGui.QLineEdit,"MainPage_Poids" + str(id_peson)).text()))
     
     
    			if combinaison_trouvee == 1:
    				result=[(combi,len(da),sum(da),min(da),max(da))
    					for nbCombi in range(NbMini,NbMaxi +1)
    						for combi,da in zip(ite.combinations(items, nbCombi),ite.combinations(data, nbCombi))]
     
    				df=pd.DataFrame(result,columns=["Combinaison","Nb","Poids","Min","Max"])
    				print(df)
    			app.processEvents()
    Merci encore de votre aide

  5. #5
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Ça ne dit pas comment le thread est invoqué.

    Par contre, d'où vient le ui ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    				if int(ui.MainPage_GroupPesons.findChild(........
    et le app ?

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 61
    Par défaut
    Le ui c'est pour le user interface , et app c'est l'application: j'ai repris des standards montrés dans des exemples.... je me demande même si ce n'est pas des choses automatiquement créées quand on convertit un fichier qtdesigner vers py ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    if __name__ == "__main__":
    	import sys
    	app = QtGui.QApplication(sys.argv)
    	Form = QtGui.QWidget()
    	ui = Ui_Form()
    	ui.setupUi(Form)
    	Form.show()
    	sys.exit(app.exec_())
    Quand à l'invocation du thread: un bouton est lié à cette fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def Calcul_Start(self):
    		calcul = Calcul()
    		calcul.start()
    		calcul.wait()

Discussions similaires

  1. Recherche avec plusieurs critères et mise à jour automatique
    Par emowpya dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 23/02/2013, 17h36
  2. Réponses: 9
    Dernier message: 28/03/2011, 14h28
  3. Problèmes dans la mise à jour de l'interface
    Par Titelouve dans le forum EDT/SwingWorker
    Réponses: 3
    Dernier message: 14/03/2011, 18h59
  4. Mise à jour de l'interface hors EDT
    Par fr1man dans le forum EDT/SwingWorker
    Réponses: 4
    Dernier message: 14/02/2007, 21h59
  5. Recherche simplicité de mise oeuvre : BDD et Interface graphique
    Par johnnyjohnny dans le forum Décisions SGBD
    Réponses: 4
    Dernier message: 28/06/2006, 15h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo