Partage
  • Partager sur Facebook
  • Partager sur Twitter

RecursionError: maximum recursion depth exceeded w

    22 septembre 2022 à 15:32:43

    Bonjour, 

    J'utilise PyQt5 et je cherche à modifier des valeurs d'une ligne de texte éditable de manière automatique. J'ai ma fréquence max, min et le span qui doivent se modifierr dès le changement d'une des 3 valeurs

    Quand une valeur change, ca change les autres à base de calcules(addition soustraction). Ca fonctionne avec un seule des 3 choix mais quand j'essaie de les combiner ca ne veut pas. J'ai cette erreur

    RecursionError: maximum recursion depth exceeded while calling a Python object
    


    dès la première tentative d'écriture.

    Voici ma manière d'appeler le changement d'écriture : 

    self.linee_freqmax.textChanged.connect(self.change_fmin)
    self.linee_freqmin.textChanged.connect(self.change_fmin)
    self.linee_span.textChanged.connect(self.change_fmin)




    Et ici ma fonction : 

        def change_fmin(self):
            if self.linee_freqmin.text() != '' or self.linee_span.text() != '' or self.linee_freqmax.text() != '' :
                if self.linee_freqmin.text() != '' :
                    self.auto_freqmin = self.linee_freqmin.text()
                    self.auto_freqmin = float(self.auto_freqmin)
                else:
                    self.auto_freqmin = 0.0
                if self.linee_span.text() != '' :
                    self.auto_span = self.linee_span.text()
                    self.auto_span = float(self.auto_span)
                else:
                    self.auto_span= 0.0
                if self.linee_freqmax.text() != '' :
                    self.auto_freqmax = self.linee_freqmax.text()
                    self.auto_freqmax = float(self.auto_freqmax)
                else:
                    self.auto_freqmax= 0.0
    
                self.freqmax_modif = float(self.auto_freqmin) + float(self.auto_span)
                self.freqspan_modif = float(self.auto_freqmin) + float(self.auto_freqmax)
                self.freqmin_modif = float(self.auto_freqmax) + float(self.auto_span)
                self.linee_freqmax.setText(str(self.freqmax_modif))
                self.linee_span.setText(str(self.freqspan_modif))
                self.linee_freqmin.setText(str(self.freqmin_modif))
            else :
                pass
    (Je ne sais pas pourquoi le premier if, une partie parait en commentaire sur le site, pas sur mon code)

    Merci à vous, Alexis

    -
    Edité par Alexismgn 22 septembre 2022 à 15:35:36

    • Partager sur Facebook
    • Partager sur Twitter
      22 septembre 2022 à 16:52:02

      c'est que le changement de l'un entraine le changement des autres et chacun de ces changements entraine à leur tour le changement des 2 autres etc etc ce qui fait que ça appelle sans cesse (en cascade) l'événement de changement sans jamais en sortir d'où l'erreur de récursion max atteinte.

      Il faut mettre en place un moyen pour que lorsque tu en changes un, ne pas déclencher les évènements de changement le temps de leur mise à jour, puis réautoriser leur évènement de changement.

      • Partager sur Facebook
      • Partager sur Twitter
        22 septembre 2022 à 17:15:30

        Salut,

        Pour compléter la réponse de @umfred pour bloquer les signaux c'est la méthode :

        .blockSignals(True)

        et pour les réactiver :

        .blockSignals(False)




        • Partager sur Facebook
        • Partager sur Twitter
          23 septembre 2022 à 11:16:18

          Bonjour je comprends le soucis, mais je n'arrive pas a comprendre la difference avec le cas où je changeais uniquement la valeur de la frequence min, ca modifier à l'instant t toutes les autres.

          Et, sachant que je ne peux editer qu'un texte à la fois que je modifie la frequence min ou un autre, rien ne devrait changer non ? Car à chaque fois un seul textEdited() est appelé.

          J'arrive à visualiser l’utilisation des signaux dans mon cas @Garkam mais je ne sais absolument pas le placer dans mon code. 

          Ca serait quelque chose comme cela ? :

          def change_fmin(self):
              #Creation SIGNAL
             
              if self.linee_freqmin.text() != '' or self.linee_span.text() != '' or self.linee_freqmax.text() != '' :
                  #BLOCK SIGNAL = TRUE
                  if self.linee_freqmin.text() != '' :
                      self.auto_freqmin = self.linee_freqmin.text()
                      self.auto_freqmin = float(self.auto_freqmin)
                  else:
                      self.auto_freqmin = 0.0
                  if self.linee_span.text() != '' :
                      self.auto_span = self.linee_span.text()
                      self.auto_span = float(self.auto_span)
                  else:
                      self.auto_span= 0.0
                  if self.linee_freqmax.text() != '' :
                      self.auto_freqmax = self.linee_freqmax.text()
                      self.auto_freqmax = float(self.auto_freqmax)
                  else:
                      self.auto_freqmax= 0.0
           
                  #BLOCK SIGNAL = FALSE
          
                  self.freqmax_modif = float(self.auto_freqmin) + float(self.auto_span)
                  self.freqspan_modif = float(self.auto_freqmin) + float(self.auto_freqmax)
                  self.freqmin_modif = float(self.auto_freqmax) + float(self.auto_span)
                  self.linee_freqmax.setText(str(self.freqmax_modif))
                  self.linee_span.setText(str(self.freqspan_modif))
                  self.linee_freqmin.setText(str(self.freqmin_modif))
              else :
                  pass

          -
          Edité par Alexismgn 23 septembre 2022 à 11:18:26

          • Partager sur Facebook
          • Partager sur Twitter
            23 septembre 2022 à 13:11:49

            Salut,

            Sur le principe, tu as raison, tu as un problème de conception.

            Logiquement, si tu modifies un QlineEdit, les 2 autres sont modifiés et c'est bon, pas besoin de bloquer les signaux, mais là dans ta méthode le QlineEdit modifié change également de valeur et du coup, on boucle indéfiniment jusqu'au plantage ...

            Pas besoin de créer les signaux c'est fait par la méthode .connect()

            là, le but est de bloquer pour comprendre d'ou vient le bug :

                def change_fmin(self):
             
                    if self.linee_freqmin.text() != '' or self.linee_span.text() != '' or self.linee_freqmax.text() != '' :
                        # Blocage
                        self.linee_freqmax.blockSignals(True)
                        self.linee_span.blockSignals(True)
                        self.linee_freqmin.blockSignals(True)
                
                        if self.linee_freqmin.text() != '' :
                            self.auto_freqmin = self.linee_freqmin.text()
                            self.auto_freqmin = float(self.auto_freqmin)
                        else:
                            self.auto_freqmin = 0.0
                        if self.linee_span.text() != '' :
                            self.auto_span = self.linee_span.text()
                            self.auto_span = float(self.auto_span)
                        else:
                            self.auto_span= 0.0
                        if self.linee_freqmax.text() != '' :
                            self.auto_freqmax = self.linee_freqmax.text()
                            self.auto_freqmax = float(self.auto_freqmax)
                        else:
                            self.auto_freqmax= 0.0
                
                        self.freqmax_modif = float(self.auto_freqmin) + float(self.auto_span)
                        self.freqspan_modif = float(self.auto_freqmin) + float(self.auto_freqmax)
                        self.freqmin_modif = float(self.auto_freqmax) + float(self.auto_span)
                        self.linee_freqmax.setText(str(self.freqmax_modif))
                        self.linee_span.setText(str(self.freqspan_modif))
                        self.linee_freqmin.setText(str(self.freqmin_modif))
                
                        # Déblocage
                        self.linee_freqmax.blockSignals(False)
                        self.linee_span.blockSignals(False)
                        self.linee_freqmin.blockSignals(False)
                
                    else :
                        pass





            -
            Edité par Garkam 23 septembre 2022 à 13:27:45

            • Partager sur Facebook
            • Partager sur Twitter
              23 septembre 2022 à 19:08:20

              Si, comme j'ai essayé de l'expliquer, si quand tu modifies min, ça modifie max; cette modification génère (sauf erreur de ma part) l'événement de modification de max; donc dans cet événement, on modifie du coup span; cette modification génère l'événement de modification de span, qui va a son tour modifier min, etc etc.

              dans la doc https://www.riverbankcomputing.com/static/Docs/PyQt4/qlineedit.html#textChanged 

              void textChanged (const QString&)
              This is the default overload of this signal.
              This signal is emitted whenever the text changes. The text argument is the new text.
              Unlike textEdited(), this signal is also emitted when the text is changed programmatically, for example, by calling setText().

              void textEdited (const QString&)
              This is the default overload of this signal.
              This signal is emitted whenever the text is edited. The text argument is the new text.
              Unlike textChanged(), this signal is not emitted when the text is changed programmatically, for example, by calling setText().

              https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/QLineEdit.html#detailed-description 

              When the text changes the textChanged() signal is emitted; when the text changes other than by calling setText() the textEdited() signal is emitted; when the cursor is moved the cursorPositionChanged() signal is emitted; and when the Return or Enter key is pressed the returnPressed() signal is emitted.

              Donc il vaut mieux utilisé textEdited que textChanged

              • Partager sur Facebook
              • Partager sur Twitter
                26 septembre 2022 à 10:56:26

                Merci à vous deux, ca fonctionne. Mais, j'ai un soucis bien compliqué où je pense que c'est ma syntaxe. 

                Quand j'écris dans un des 3 champs, ca n'affiche pas la valeur que je suis entrain d'écrire sur le clavier mais la valeur modifié en temps réel avec les équations. J'ai fais un test qu'avec fmin et fmax

                j'ai simulé que si fmax.textEdited() => fmin = fmax +80 

                                         fmin.textEdited() => fmax = fmin +40 

                Résultat : quand j'écris juste 4 pour fmin, fmax vaut bien 44, mais fmin devient 124 (4 + 40 +80), il a rebouclé lui même. 

                J'ai essayé de changer de place le setText mais rien n'y fais. Egalement, je ne peux plus y supprimer le texte. 

                Je me demande s'il serait pas mieux de créer 3 fonctions pour les 3 zones de texte et traiter chaque cas indépendemment. Qu'en pensez-vous ? Si c'est une solution plus longue et qui demande trop de ressource je resterais sur ce principe là 

                Alexis

                • Partager sur Facebook
                • Partager sur Twitter
                  26 septembre 2022 à 11:30:55

                  quand il y a plusieurs champs interdépendants, il faut faire à attention à l'ordre de modifications de champs, une fonction par champ peut être une solution ou une fonction à laquelle on indique qui est à la source de l'appel pour éviter de modifier cette source
                  • Partager sur Facebook
                  • Partager sur Twitter

                  RecursionError: maximum recursion depth exceeded w

                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                  • Editeur
                  • Markdown