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 :

Comment exécuter une fonction la perte de focus QCombobox Pyqt6 ? [QtGui]


Sujet :

PyQt Python

  1. #1
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Janvier 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2008
    Messages : 110
    Par défaut Comment exécuter une fonction la perte de focus QCombobox Pyqt6 ?
    Bonjour à tous,

    Je débute avec Python et plus encore avec Qt, j'ai mis en place mon IHM avec quelques Widgets tel que Tableview où j'ai pu charger celui-ci avec une BDD.

    Aujourd'hui, je souhaite exécuter une fonction lorsque je perds le focus d'une combobox. J'ai trouvé une fonction d'une Widget Combobox nommée "focusOutEvent", je pense être sur la bonne voie mais honnêtement je galère à trouver une solution, c'est d'ailleurs pour cela que je vous écris aujourd'hui.

    Je voudrais savoir si vous auriez une idée sur comment mettre en place mon objectif ?

    Je vous met ci-dessous un petit bout de mon code ciblé sur ce Widget :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    class MainWindow(QMainWindow):
        self.combo = ComboBox(frame)
        self.combo.focusOutEvent()
     
     
    class ComboBox(QComboBox):
        def focusOutEvent(self, event=QFocusEvent):
            super().focusOutEvent(event)
    En vous remerciant à tous d'avance pour votre aide.

  2. #2
    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,

    Voilà un petit code de test (à lancer dans une console pour avoir les print):

    on a une fenêtre QWidget, contenant un QCombobox et un QLineEdit.

    Au lancement, le combobox prend le focus. En cliquant sur le QLineEdit, le combobox perd le focus. Etc...


    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    import sys
    from PyQt5 import (QtCore, QtWidgets)
     
    #############################################################################
    class Fenetre(QtWidgets.QWidget):
     
        # =======================================================================
        def __init__(self, parent=None):
            super().__init__(parent)
            self.resize(400, 300)
     
            self.combo = QtWidgets.QComboBox(self)
     
            self.line = QtWidgets.QLineEdit(self)
     
            posit = QtWidgets.QGridLayout()
            posit.addWidget(self.combo, 0, 0)
            posit.addWidget(self.line, 1, 0)
            self.setLayout(posit)
     
            self.combo.focusInEvent = self.focusInEvent
            self.combo.focusOutEvent = self.focusOutEvent
     
            self.combo.setFocus()
            self.combofocus = True
     
        # =======================================================================
        def focusInEvent(self, event):
     
            if self.combo.hasFocus():
                print("le combo prend le focus!")
                self.combofocus = True
                event.accept()
            else:
                super().focusInEvent(self, event)
     
        # =======================================================================
        def focusOutEvent(self, event):
     
            if self.combofocus:
                print("le combo perd le focus!")
                self.combofocus = False
                event.accept()
            else:
                super().focusOutEvent(self, event)
     
    #############################################################################
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        fen = Fenetre()
        fen.show()
        sys.exit(app.exec_())

  3. #3
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Janvier 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2008
    Messages : 110
    Par défaut
    Bonjour tyrtamos,

    Tout d'abord, merci pour ton aide c'est très gentil !

    Dans un 1er temps, j'ai essayé ton code est il fonctionne très bien. Ensuite j'ai voulu l'adapter à ce que j'ai fait, idem ça fonctionne, cependant j'ai un petit soucis.

    Lorsque je quitte la combobox, le curseur reste et j'en ai un nouveau qui apparaît en fonction du Widget que j'utilise (ex : lineEdit apparaît un nouveau curseur et dans la combo le curseur est toujours présent).
    Je ne vois pas pourquoi celui-ci reste ?

    Ensuite, j'ai un autre soucis. Si je laisse la section :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            else:
                super().focusOutEvent(self, event)
    J'ai un message d'erreur venant de l'éditeur concernant la variable "event", il me marque "Unexpected argument ", pour info : J'utilise Pyqt6 (peut-être que c'est ça le soucis).

    En te remerciant d'avance pour ton aide.

  4. #4
    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

    Citation Envoyé par Jb_One36 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
            else:
                super().focusOutEvent(self, event)
    J'ai un message d'erreur venant de l'éditeur concernant la variable "event", il me marque "Unexpected argument ", pour info : J'utilise Pyqt6 (peut-être que c'est ça le soucis).
    Erreur de ma part: il faut retirer le "self, "

    Je regarde les autres aspects.

  5. #5
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Janvier 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2008
    Messages : 110
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Bonjour



    Erreur de ma part: il faut retirer le "self, "

    Je regarde les autres aspects.
    -----------------------------------------------------------------------
    Merci pour ton aide tyrtamos !

    Après en réfléchissant sur ce que tu as écrit, je pense que j'aurai pu trouver pour cette partie.
    Par contre, pour l'histoire du focus, j'avoue ne pas comprendre ???

    En tout cas, merci beaucoup.

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 814
    Billets dans le blog
    1
    Par défaut
    Salut

    Citation Envoyé par tyrtamos Voir le message
    Je regarde les autres aspects.
    J'adore quand tu postes un code car j'apprends plein de trucs. Ici aussi je me suis empressé de le tester.

    J'ai quand-même une petite question sur le fait que tu n'appelles super() que dans le cas où le combo n'a pas le focus.
    Dans ma logique, j'aurais écrit les focusIn et focusOut ainsi
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def focusInEvent(self, event):
    	super().focusInEvent(event)
    	if self.combo.hasFocus():
    		print("le combo prend le focus!")
    		self.combofocus = True
     
    def focusOutEvent(self, event):
    	super().focusOutEvent(event)
    	if self.combofocus:
    		print("le combo perd le focus!")
    		self.combofocus = False

    De fait, cette solution (dans laquelle j'ai viré le event.accept() que je ne pense pas utile) semble donner le même résultat...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    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

    Citation Envoyé par Sve@r Voir le message
    J'adore quand tu postes un code car j'apprends plein de trucs. Ici aussi je me suis empressé de le tester.
    Et tes questions pertinentes me poussent dans mes retranchements et me forcent à progresser: merci!

    J'ai recherché sur le web, et comme souvent, je retrouve mes propres écrits (!). J'ai ainsi trouvé ce fil ancien de 2010 qui traite du sujet:
    https://www.developpez.net/forums/d9...ent-qlineedit/

    Je préfère nettement la solution décrite dans le message #7 de ce fil. Après conversion en Python 3 et adaptation au problème présent, voilà ce que ça donne (à lancer dans une console pour avoir les prints):

    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
    36
    37
    38
    39
    40
    41
    import sys
    from PyQt5 import QtCore, QtGui, QtWidgets
     
    #############################################################################
    class MyComboBox(QtWidgets.QComboBox):
     
        def focusOutEvent(self, event):
            print("Le combobox perd le focus")
            super().focusOutEvent(event)
     
        def focusInEvent(self, event):
            print("Le combobox prend le focus")
            super().focusInEvent(event)
     
    #############################################################################
    class Fenetre(QtWidgets.QWidget):
     
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setWindowTitle("Code test pour focus event")
            self.resize(400, 300)
     
            # créer le QComboBox perso
            self.combo = MyComboBox(self)
            self.combo.setEditable(True) # pour voir le caret avec le focus
     
            # créer le QLineEdit
            self.lineEdit = QtWidgets.QLineEdit(self)
     
            # positionne des 2 widgets dans la fenêtre
            posit = QtWidgets.QGridLayout()
            posit.addWidget(self.combo, 0, 0)
            posit.addWidget(self.lineEdit, 1, 0)
            self.setLayout(posit)
     
    #############################################################################
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        fen = Fenetre()
        fen.show()
        sys.exit(app.exec_())
    [edit] Et s'il faut mener une action dans la fenêtre principale en cas de perte de focus du QComboBox spécial, on peut, à partir du focusOutEvent, envoyer un message (emit) avec un signal spécifique (à créer). On peut facilement adapter le code ci-dessus:

    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    import sys
    from PyQt5 import QtCore, QtGui, QtWidgets
     
    #############################################################################
    class MyComboBox(QtWidgets.QComboBox):
     
        # crée un nouveau signam
        focusChange = QtCore.pyqtSignal(str)
     
        def focusOutEvent(self, event):
            self.focusChange.emit("La 1ère ligne perd le focus")
            super().focusOutEvent(event)
     
        def focusInEvent(self, event):
            self.focusChange.emit("La 1ère ligne prend le focus")
            super().focusInEvent(event)
     
    #############################################################################
    class Fenetre(QtWidgets.QWidget):
     
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setWindowTitle("Code test pour focus event")
            self.resize(400, 300)
     
            # créer le QComboBox perso
            self.combo = MyComboBox(self)
            self.combo.setEditable(True) # pour voir le caret avec le focus
            self.combo.focusChange.connect(self.comboFocus)
     
            # créer le QLineEdit
            self.lineEdit = QtWidgets.QLineEdit(self)
     
            # positionne des 2 widgets dans la fenêtre
            posit = QtWidgets.QGridLayout()
            posit.addWidget(self.combo, 0, 0)
            posit.addWidget(self.lineEdit, 1, 0)
            self.setLayout(posit)
     
        def comboFocus(self, msg):
            print(msg)
     
    #############################################################################
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        fen = Fenetre()
        fen.show()
        sys.exit(app.exec_())

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 814
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Je préfère nettement la solution décrite dans le message #7 de ce fil. Après conversion en Python 3 et adaptation au problème présent, voilà ce que ça donne......Et s'il faut mener une action dans la fenêtre principale en cas de perte de focus du QComboBox spécial, on peut, à partir du focusOutEvent, envoyer un message (emit) avec un signal spécifique (à créer).
    Effectivement là on passe dans le 100% objet donc 100% propre. Ce qui évite en plus de remplacer les combo.focusInEvent et combo.focusOutEvent originels dans ton premier code (ça je n'y aurais jamais pensé).
    Ce code là me parle et correspond aussi à ma façon habituelle de faire. Mais ma question portait surtout sur le premier code à propos du super() que je voyais obligatoire et du accept() que lui je voyais inutile. Mais en fait en le remplaçant par un ignore() et en allant même jusqu'à supprimer les super() ça marche toujours pareil...
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def focusInEvent(self, event):
    	event.ignore()
    	#super().focusInEvent(event)
    	if self.combo.hasFocus():
    		print("le combo prend le focus!")
     
    def focusOutEvent(self, event):
    	event.ignore()
    	#super().focusOutEvent(event)
    	if not self.combo.hasFocus():
    		print("le combo perd le focus!")
    Bref je sais plus trop quoi en penser (rôle du super(), du accept(), du ignore()) dans le cadre de ce premier code...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    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
    Citation Envoyé par Sve@r Voir le message
    Bref je sais plus trop quoi en penser (rôle du super(), du accept(), du ignore()) dans le cadre de ce premier code...
    J'ai une logique en tête que j'applique, mais quelquefois, j'oublie de l'appliquer et ça marche quand même... En fait, ça dépend en grande partie de ce qui a été programmé en C++, et la lecture, même attentive, de la notice, n'en dit pas assez sur le sujet.

    Je vais te donner ma logique, avec 2 exemples qui fonctionnent:

    1- super

    Quand on crée une nouvelle classe fille, si on surcharge un gestionnaire d'évènement, on ne doit utiliser super que quand ce gestionnaire n'a pas tout fait et qu'il faut repasser la main à celui de l'ancêtre.

    Exemple avec keyPressEvent:

    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
    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
     
    import sys
    from PyQt5 import (QtWidgets, QtCore)
     
    #############################################################################
    class MyLineEdit(QtWidgets.QLineEdit):
     
        def keyPressEvent(self, event):
            if event.key() == QtCore.Qt.Key_Escape:
                self.clear()
            else:
                super().keyPressEvent(event)  
     
    #############################################################################
    class Fenetre(QtWidgets.QWidget):
     
        def __init__(self, parent=None):
            super().__init__(parent)
     
            self.line = MyLineEdit(self)
     
    #############################################################################
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        fen = Fenetre()
        fen.show()
        sys.exit(app.exec_())
    Avec ce code, si je tape n'importe quelle touche (sauf escape), le QLineEdit affiche la touche tapée. Si je fais escape, la ligne est vidée.
    Mais si je retire le super().keyPressEvent(event), plus rien n'est reçu par le QLineEdit, ce qui parait normal.

    2- event.accept() et event.ignore()

    Au code précédent, j'ajoute une gestionnaire d'évènement closeEvent. Il est appelé à chaque fermeture de la fenêtre, quelque soit la méthode utilisée (y compris la croix de la fenêtre).

    Cela donne:

    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
    36
    37
    38
    39
    40
    41
    42
    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
     
    import sys
    from PyQt5 import (QtWidgets, QtCore)
     
    #############################################################################
    class MyLineEdit(QtWidgets.QLineEdit):
     
        def keyPressEvent(self, event):
            if event.key() == QtCore.Qt.Key_Escape:
                self.clear()
            else:
                super().keyPressEvent(event)  
     
    #############################################################################
    class Fenetre(QtWidgets.QWidget):
     
        def __init__(self, parent=None):
            super().__init__(parent)
     
            self.line = MyLineEdit(self)
     
        def closeEvent(self, event):
            """lancé à la fermeture de la fenêtre quelqu'en soit la méthode
            """
            reponse = QtWidgets.QMessageBox.question(self,
                        "Fermeture de la fenêtre",
                        "Voulez-vous vraiment?",
                        QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
     
            if reponse != QtWidgets.QMessageBox.Yes:
                event.ignore() # => fermeture refusée
            else:
                event.accept() # => fermeture acceptée
     
    #############################################################################
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        fen = Fenetre()
        fen.show()
        sys.exit(app.exec_())
    Dans ce cas, à chaque tentative de fermeture, la question "voulez-vous vraiment?" sera posée, et selon la réponse, la fermeture sera acceptée (event.accept()) ou refusée (event.ignore()).

    Voilà. Ces 2 cas simples représentent ce que j'ai compris du sujet. Mais sur d'autres cas, je suis moins brillant() et je me contente de me débrouiller pour que ça marche... Mais j'aimerais bien que ce soit plus "carré"!

  10. #10
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 814
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    1- super

    Quand on crée une nouvelle classe fille, si on surcharge un gestionnaire d'évènement, on ne doit utiliser super que quand ce gestionnaire n'a pas tout fait et qu'il faut repasser la main à celui de l'ancêtre.

    Exemple avec keyPressEvent...
    Avec ce code, si je tape n'importe quelle touche (sauf escape), le QLineEdit affiche la touche tapée. Si je fais escape, la ligne est vidée.
    Mais si je retire le super().keyPressEvent(event), plus rien n'est reçu par le QLineEdit, ce qui parait normal.
    Et si tu le mets dans tous les cas ?
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def keyPressEvent(self, event):
    	super().keyPressEvent(event)
    	if event.key() == QtCore.Qt.Key_Escape:
    		self.clear()
    style (autre logique possible) je demande au gestionnaire de faire ce qu'il fait d'habitude puis je rajoute mes trucs. Après-tout, quand tu dis "... que quand ce gestionnaire n'a pas tout fait" tu ne sais pas si ce que toi tu as fait correspond à tout ce qu'il fallait faire...

    Citation Envoyé par tyrtamos Voir le message
    2- event.accept() et event.ignore()

    Au code précédent, j'ajoute une gestionnaire d'évènement closeEvent. Il est appelé à chaque fermeture de la fenêtre, quelque soit la méthode utilisée (y compris la croix de la fenêtre).
    Oui ce cas je connaissais. Je le montre d'ailleurs ici: https://pyqt.developpez.com/telechar...17/Les-widgets.
    J'ai même découvert aujourd'hui setAccepted() qui permet de supprimer le if/else => event.setAccepted(reponse == QtWidgets.QMessageBox.Yes). Je suis en train de réfléchir si je remplace, dans mes codes, accept()/ignore() par cette nouvelle possibilité (quand je trouve un nouveau truc qui simplifie un truc que j'ai déjà fait, je le replace alors dans tous mes sources qui l'utilisent => le "gvim" il chauffe à ce moment là...)

    Mais c'était dans le focusIn et focusOut que je voyais pas son utilité. Et ça semble plutôt logique qu'il n'y soit pas. Après-tout, comment devrait se comporter l'évènement si on le refuse? De toute façon le focus est déjà acté...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  11. #11
    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

    Citation Envoyé par Sve@r Voir le message
    Et si tu le mets dans tous les cas ?
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def keyPressEvent(self, event):
    	super().keyPressEvent(event)
    	if event.key() == QtCore.Qt.Key_Escape:
    		self.clear()
    style (autre logique possible) je demande au gestionnaire de faire ce qu'il fait d'habitude puis je rajoute mes trucs. Après-tout, quand tu dis "... que quand ce gestionnaire n'a pas tout fait" tu ne sais pas si ce que toi tu as fait correspond à tout ce qu'il fallait faire...
    Imagine que escape ait déjà une fonction dans le QLineEdit que tu utilises. Tu décides qu'il doit maintenant vider la ligne, mais plus son ancienne fonction: dans ce cas, tu ne dois pas appliquer super() à chaque touche escape!


    Quant à accept et ignore, les choses sont plus complexes qu'on ne le pense souvent parce que, comme je l'ai dit, ça dépend de la manière dont le codage en C++ a été fait, dans le mécanisme d'héritage entre objets. Voilà un extrait traduit (merci google) de la doc de Qt5 concernant QEvent (c'est moi qui ait mis en gras):

    La boucle d'événements principale de Qt (QCoreApplication::exec()) récupère les événements du système de fenêtrage natif de la file d'attente d'événements, les traduit en QEvents et envoie les événements traduits à QObjects.

    En général, les événements proviennent du système de fenêtres sous-jacent (spontaneous() renvoie true), mais il est également possible d'envoyer manuellement des événements en utilisant QCoreApplication::sendEvent() et QCoreApplication::postEvent() (spontaneous() renvoie false).

    Les QObjects reçoivent des événements en faisant appeler leur fonction QObject::event(). La fonction peut être réimplémentée dans des sous-classes pour personnaliser la gestion des événements et ajouter des types d'événements supplémentaires*; QWidget::event() est un exemple notable. Par défaut, les événements sont distribués aux gestionnaires d'événements tels que QObject::timerEvent() et QWidget::mouseMoveEvent(). QObject::installEventFilter() permet à un objet d'intercepter des événements destinés à un autre objet.

    Le QEvent de base ne contient qu'un paramètre de type d'événement et un drapeau "accepter". L'indicateur d'acceptation est défini avec accept() et effacé avec ignore(). Il est défini par défaut, mais ne vous y fiez pas car les sous-classes peuvent choisir de l'effacer dans leur constructeur.

    Les sous-classes de QEvent contiennent des paramètres supplémentaires qui décrivent l'événement particulier.
    Doc d'origine ici: https://doc.qt.io/qt-5.15/qevent.html

    Mais finalement, peut-être faut-il considérer que accept et ignore n'ont pas d'action (et quelquefois pas de sens!) quand la doc de l'évènement considéré n'en parle pas! Et c'est le cas de focusOutEvent:
    https://doc.qt.io/qt-5/qwidget.html#focusOutEvent

  12. #12
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 814
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Imagine que escape ait déjà une fonction dans le QLineEdit que tu utilises. Tu décides qu'il doit maintenant vider la ligne, mais plus son ancienne fonction: dans ce cas, tu ne dois pas appliquer super() à chaque touche escape!
    Effectivement, cas extrème totalement opposé. Mais y a-t-il un moyen de savoir ?
    Remarque j'ai déjà eu ce cas. Dans mes applis, mes fenêtres de gestion ont 2 façons d'être appelées
    1. pour remplir la bdd => dans ce cas, elle s'ouvre en plein écran et on ne la ferme que par bouton
    2. pour offrir à l'utilisateur la liste des éléments disponibles. Si par exemple ma fenêtre "client" permet d'ajouter/modifier/supprimer un client, si je l'appelle en mode "info" depuis une autre fenêtre (ex "remise") elle affiche la liste des clients existants et l'utilisateur peut en sélectionner un qui remonte à l'appelant (accessoirement il peut aussi le modifier s'il constate une erreur puisque c'est la même fenêtre). Mais s'il décide finalement de ne pas choisir de client alors il peut taper "Esc" et la fenêtre se referme sans renvoyer de client


    Voici comment j'ai codé le keyPressEvent de ce type de fenêtre
    Code python : 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
    def keyPressEvent(self, event):
    	# Gestion de la touche "escape"
    	if event.key() == Qt.Key_Escape:
    		# Si on est en mode récupération
    		if self._fl_recup:
    			# Appel méthode objet hérité
    			super().keyPressEvent(event)
     
    			# Fermeture fenêtre
    			self.close()
    		# if
     
    		# La fonction n'a plus rien à faire
    		return
    	# if
     
    	# Appel méthode objet hérité
    	super().keyPressEvent(event)
    # keyPressEvent()

    Obligé de coder deux fois super(), car il faut distinguer si on appuie sur "esc" en mode "récupération" (cas n° 2) sinon "Esc" ne doit pas avoir d'effet (car par défaut il ferme la fenêtre); et le second pour les autres keyEvent qui ne concernent pas Esc.
    A noter en plus que quand on appuie sur "esc", un QDialog se ferme sans passer par closeEvent (c'est pour ça que je rajoute un close() dans mon code car dans closeEvent je fais un tas de libérations).

    Citation Envoyé par tyrtamos Voir le message
    Mais finalement, peut-être faut-il considérer que accept et ignore n'ont pas d'action (et quelquefois pas de sens!) quand la doc de l'évènement considéré n'en parle pas! Et c'est le cas de focusOutEvent:
    Dans ce cas quel conseil aurais-tu? Faut-il toujours les mettre dans nos fonctions de surcharge Event en se disant "comme ça si c'est nécessaire il y est" (un peu comme un free() en C qu'on met dans tous les cas y compris si le pointeur est NULL) ou bien faut-il réfléchir à chaque Event en se demandant s'il est nécessaire ou pas ?
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  13. #13
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Janvier 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2008
    Messages : 110
    Par défaut
    Bonjour et merci à tous pour vos réponses (je ne pensais pas que du simple question basique je suppose, j'aurai pu faire autant de débats (positif)).

    J'ai donc pu recopier et adapter en fonction de mes besoins ce que tyrtamos a noté en indice #7, cela fonctionne parfaitement ... merci pour tout !!!

    Je n'ai plus le focus qui reste dans le widget combobox.

    En revanche, étant vraiment débutant avec Python, je n'ai pas tout compris de vos échange surtout concernant la fonction super(), je voudrais donc savoir si vous auriez pas un tuto ou quelques choses de ce genre à me communiquer pour que je poursuivre ma formation (autodidacte pur) et ainsi, pouvoir compléter cette communiquer d'entraide.

    Aujourd'hui je pose des questions mais j'aimerai bien à l'avenir faire parti de cette élite.

    En vous remerciant d'avance et aussi pour l'aide que vous m'avez apporté.

    A très bientôt.

  14. #14
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 814
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Jb_One36 Voir le message
    Bonjour et merci à tous pour vos réponses (je ne pensais pas que du simple question basique je suppose, j'aurai pu faire autant de débats (positif)).
    Héhé, c'est que Qt c'est un gros truc et c'est pas facile à apréhender dans sa globalité et plus on en sait plus on se rend compte qu'on doit en apprendre encore. Il y a des évènements qui se produisent, qui ne se produisent pas, qui doivent se produire. Rien que le fait que "esc" ferme un QDialog sans passer par closeEvent() m'a mis un bordel avant que je m'en rende compte... plus certains bugs (par exemple dans Qt4 un retour arrière dans un QLineEdit produisait deux signaux "édité" !!!)

    Citation Envoyé par Jb_One36 Voir le message
    En revanche, étant vraiment débutant avec Python, je n'ai pas tout compris de vos échange surtout concernant la fonction super(), je voudrais donc savoir si vous auriez pas un tuto ou quelques choses de ce genre à me communiquer pour que je poursuivre ma formation (autodidacte pur) et ainsi, pouvoir compléter cette communiquer d'entraide.
    Ben justement mon tuto Python a été accepté et commence à être mis en ligne => https://frederic-lang.developpez.com...ython-de-zero/

    En fait (petit résumé rapide), super() concerne l'héritage. Tu crées un objetX qui hérite d'un objet existant, si cet objet existant contient une méthode toto() mais que toi tu veux créer ta propre méthode toto() qui fasse comme l'originelle plus des trucs à toi, tu peux utiliser super().toto() pour effectuer les actions du toto() d'origine (sans même avoir besoin de les connaitre) avant de coder tes propres actions en plus.
    Cela se traduit par
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class objetX(objetOrigine):
    	def toto(self):
    		# D'abord le toto d'origine
    		super().toto()
     
    		# Maintenant mes trucs à moi
    		...
    	# toto()
    # objetX
    Cela permet de garder la compatibilité descendante avec ceux qui utilisent les objets en question. Celui qui utilisait l'objet de base et qui appelait objet.toto() pourra remplacer dans son code cet objet par le tien sans rien changer d'autre, il continuera à appeler objet.toto() en étant sûr de garder au minimum le comportement d'origine.

    Cette fonction super() est un raccourci de la façon de faire d'avant dans laquelle on devait spécifier l'héritage explicite et qui était bien alors plus lourde
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class objetX(objetOrigine):
    	def toto(self):
    		# D'abord le toto d'origine
    		objetOrigine.toto(self)
     
    		# Maintenant mes trucs à moi
    		...
    	# toto()
    # objetX

    Tu peux aussi aller télécharger mes exemples PyQt permettant de bien débuter dans ce domaine. Le premier https://pyqt.developpez.com/telechar.../47/Hello-Word
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  15. #15
    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
    Citation Envoyé par Sve@r Voir le message
    Dans ce cas quel conseil aurais-tu? Faut-il toujours les mettre dans nos fonctions de surcharge Event en se disant "comme ça si c'est nécessaire il y est" (un peu comme un free() en C qu'on met dans tous les cas y compris si le pointeur est NULL) ou bien faut-il réfléchir à chaque Event en se demandant s'il est nécessaire ou pas ?
    Jusqu'à présent, je plaçais .accept() et .ignore() assez systématiquement, "au cas où", mais maintenant, j'aurais plutôt tendance à les placer quand la doc du gestionnaire d'évènement en parle, et quand ça a un sens. Et donc, je n'aurais pas dû les mettre avec focusInEvent et focusOutEvent.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Comment exécuter une fonction jQuery depuis un flash ?
    Par supaaa_mika dans le forum jQuery
    Réponses: 0
    Dernier message: 07/11/2011, 15h42
  2. Réponses: 2
    Dernier message: 29/07/2008, 15h04
  3. Réponses: 4
    Dernier message: 21/09/2007, 15h14
  4. Réponses: 2
    Dernier message: 16/07/2007, 16h04
  5. [Débutant]Comment exécuter une fonction tous les jours
    Par pseudomh dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 21/06/2006, 16h10

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