11
votes

Connexion de machines à sous et de signaux dans Pyqt4 dans une boucle

im essayant de construire une calculatrice avec PYQT4 et de connecter les signaux "cliqués ()" des boutons ne fonctionne pas comme prévu. Je crée mes boutons pour les chiffres à l'intérieur d'une boucle pour la boucle où j'essaie de les connecter ensuite. XXX

Lorsque je clique sur les boutons Tout impressionner "9 '. Pourquoi est-ce que cela et comment puis-je résoudre ce problème?


0 commentaires

3 Réponses :


16
votes

Ceci est juste, comment la recherche et les fermetures de noms sont définies dans Python.

Python n'introduit que de nouvelles liaisons dans l'espace de noms via une affectation et via des listes de paramètres des fonctions. i code> n'est donc pas défini dans l'espace de noms du lambda code>, mais dans l'espace de noms de __ init __ () code>. Le nom Recherche i code> dans la Lambda finit par conséquent dans l'espace de noms de __ init __ () code>, où i code> est finalement lié à 9 code>. C'est ce qu'on appelle "fermeture". P>

Vous pouvez travailler autour de ces sémantiques certes et non intuitives (mais bien définies) en passant i code> comme argument de mots clés avec la valeur par défaut. Comme indiqué, les noms des paramètres introduisent de nouvelles liaisons dans l'espace de noms local, donc i code> à l'intérieur du lambda code> devient indépendant de i code> dans .__ init __ () code>: p> xxx pré>

une alternative plus lisible, moins magique est functools.Partial code>: p>

self._numberButtons[i].clicked.connect(partial(self._number, i))


1 commentaires

Merci. Je vais avec la solution FuncoTools.Partiale.



3
votes

Vous créez des fermetures. Les fermetures capturent vraiment une variable et non la valeur d'une variable. À la fin de __ init __ , i est le dernier élément de la plage (0, 10) , i.e. 9 . Tous les Lambdas que vous avez créés dans cette étendue se rapportent à ce i et uniquement lorsqu'ils sont invoqués, ils obtiennent la valeur de i au moment où elles sont invoquées (cependant, séparées Invocations de __ init __ Créez des lambdas faisant référence à des variables séparées!).

Il y a deux façons populaires pour éviter ceci:

  1. Utilisation d'un paramètre par défaut: lambda i = i: auto._number (i) . Ce travail car les paramètres par défaut lient une valeur au moment de la définition de la fonction.
  2. Définition d'une fonction d'assistance Helper = Lambda I: (Lambda: Self._Number (i)) et utilisez Helper (i) dans la boucle. Cela fonctionne car le "code extérieur" i est évalué à l'heure i est lié et - comme mentionné précédemment - la fermeture suivante créée dans la prochaine invocation de se référera à une variable différente.

0 commentaires

0
votes

Utilisez le qt WAY, utilisez QsignalMapper < / code> à la place.


3 commentaires

S'il vous plaît ne faites pas. Qsignalmapper est un reste de C ++ 98, qui n'a pas de lambdas ni de fonctions partielles et où une telle solutation est un mal nécessaire. En Python, cependant Qsignalmapper est simplement superflu et vraiment ballonné par rapport à FuncTools.Partial () ou lambda. Solutions avec partielle () ou lambda sont plus courtes et plus élégantes que qsignalmapper .


Oh bien c'est sur le choix, je choisirais qsignalmapper pour la compatibilité QT / C ++.


Bien sûr, il s'agit du choix, mais je ne comprends tout simplement pas votre choix et je ne peux pas le suivre. J'utilise Python pour les applications QT exactement parce que c'est pas C ++, et si j'abandonnerais toutes les fonctionnalités spéciales de Python à maintenir ou à atteindre la compatibilité C ++, je pourrais aussi bien utiliser C ++;)