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 :

Esc et closeEvent [QtGui]


Sujet :

PyQt Python

  1. #1
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    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 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut Esc et closeEvent
    Bonjour à tous

    J'ai remarqué que pour un QDialog, la touche "esc" le ferme sans le faire passer par un closeEvent

    Exemple
    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
    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
    #!/usr/bin/env python3
    # coding: utf-8
     
    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    import sys
     
    class myWindow(QDialog):
    	def __init__(self, *args, **kwargs):
    		super().__init__(*args, *kwargs)
    		btn=QPushButton("quit", parent=self, clicked=self.close)
    		layout=QHBoxLayout(self)
    		layout.addWidget(btn)
    	# __init__()
     
    	def closeEvent(self, event):
    		print(
    			"%s => %s.closeEvent(%s)" % (
    				self.sender().__class__.__name__,
    				self.__class__.__name__,
    				"%s (%s)" % (event.__class__.__name__, type(event)),
    			)
    		)
     
    		# Question
    		if QMessageBox.question(
    			self,
    			"Confirmation",
    			"Confirmez-vous vouloir quitter ?",
    			QMessageBox.Yes|QMessageBox.No,
    		) != QMessageBox.Yes:
    			event.ignore()
    			return
    		# if
     
    		# Appel méthode objet hérité
    		super().closeEvent(event)
    		event.accept()
    	# closeEvent()
    # class myWindow
     
    app=QApplication(sys.argv)
    d=myWindow()
    d.show()
    sys.exit(app.exec_())

    On lance le programme, si on appuie sur "quit" ou la croix on passe par le closeEvent (et on a le choix de valider ou refuser). Mais si on appuie sur "esc" la fenêtre se ferme sans rien demander.

    On peut bien entendu forcer le truc en rajoutant un keyPressEvent codé par exemple de cette façon
    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
    def keyPressEvent(self, event):
    	print(
    		"%s => %s.keyPressEvent(%s)" % (
    			self.sender().__class__.__name__,
    			self.__class__.__name__,
    			"%s (%s)" % (event.__class__.__name__, type(event)),
    		)
    	)
    	if event.key() == Qt.Key_Escape:
    		self.close()
    		return
    	# if
    	super().keyPressEvent(event)
    # keyPressEvent()

    Mais quelqu'un (tyrtamos?) sait-il si ce comportement est voulu (et pourquoi) ou bien s'il s'agit d'une erreur de conception dans Qt? Surtout que ça ne vaut que pour un QDialog. Pour un QWidget, la touche "Esc" est inactive.

    Merci à tous
    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]

  2. #2
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 461
    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 461
    Points : 9 248
    Points
    9 248
    Billets dans le blog
    6
    Par défaut
    Bonjour Sve@r

    T'as de la chance: je regarde la télé, mais j'ai un petit portable allumé à côté...

    Quand j'ai une question comme ça, je commence à regarder dans la doc: et oui, c'est prévu dans celle de QDialog !

    https://doc.qt.io/qt-5.15/qdialog.html#escape-key

    Escape Key

    If the user presses the Esc key in a dialog, QDialog::reject() will be called. This will cause the window to close: The close event cannot be ignored.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    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 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    T'as de la chance: je regarde la télé
    Ouais, il y a Buffy sur 6ter

    Citation Envoyé par tyrtamos Voir le message
    Quand j'ai une question comme ça, je commence à regarder dans la doc:
    Tiens, pan dans ma tronche Je l'ai tellement sorti aux autres...

    Ok, merci. Je pige pas trop le pourquoi (ça ne devait pas coûter grand chose que de renvoyer la fermeture via "esc" sur un close standard) ni la fin de la doc "The close event cannot be ignored" semblant vouloir dire qu'on ne peut pas bloquer l'effet du "esc" alors qu'on le peut bel et bien via keyPressEvent() comme je l'ai montré mais bon, ça reste secondaire.

    Ok, résolu.
    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]

  4. #4
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 461
    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 461
    Points : 9 248
    Points
    9 248
    Billets dans le blog
    6
    Par défaut
    C'est bien d'avoir un portable devant la télé: avec la pub, on a de plus en plus de temps... Dans le passé, pendant la pub, on en profitais pour aller au WC, mais maintenant, on a le temps de faire du Python!

    Concernant la mention "The close event cannot be ignored", je suppose que ça veut dire qu'on ne peut pas neutraliser escape avec un event.ignore() dans le closeEvent. Mais je n'ai pas essayé. De toutes façons, la solution keyPressEvent est certainement la bonne pour neutraliser escape.

    Citation Envoyé par Sve@r Voir le message
    Tiens, pan dans ma tronche Je l'ai tellement sorti aux autres...
    Et j'ai été gentil: j'aurais pu te répondre ce qu'on trouve souvent dans certains forums Linux, un simple "RTFM", c'est à dire "Relis Ton Foutu Manuel" (version française du "Read The Fucking Manual").
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    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 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    C'est bien d'avoir un portable devant la télé: avec la pub, on a de plus en plus de temps... Dans le passé, pendant la pub, on en profitais pour aller au WC, mais maintenant, on a le temps de faire du Python!
    Moi j'en ai tellement raz le bol des films qui commencent de plus en plus tard, style prévus à 21h15 mais toujours pas commencé à 21h30 cause débordements en tous genre plus pubs interminables (je me souviens d'une époque où le film était à 20h30) qu'il m'arrive parfois de télécharger le film prévu le soir pour ensuite pouvoir le regarder à ma façon et à l'heure. Je le passe le même jour mais à l'heure et sans pub. Ensuite quand il est terminé je repasse sur la chaine qui le diffuse pour voir le décalage...

    Citation Envoyé par tyrtamos Voir le message
    Concernant la mention "The close event cannot be ignored", je suppose que ça veut dire qu'on ne peut pas neutraliser escape avec un event.ignore() dans le closeEvent
    Ah ben non, on ne rentre même pas dans le closeEvent !!!
    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]

  6. #6
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    3 948
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3 948
    Points : 9 276
    Points
    9 276
    Par défaut
    Hello,
    Citation Envoyé par Sve@r Voir le message
    Mais quelqu'un (tyrtamos?) sait-il si ce comportement est voulu (et pourquoi) ou bien s'il s'agit d'une erreur de conception dans Qt? Surtout que ça ne vaut que pour un QDialog. Pour un QWidget, la touche "Esc" est inactive.
    En fait dans un QDialog la touche Esc est "câblé" sur un bouton de la QDialog avec cette règle :
    By default, QMessageBox attempts to automatically detect an escape button as follows:

    If there is only one button, it is made the escape button.
    If there is a Cancel button, it is made the escape button.
    On macOS only, if there is exactly one button with the role QMessageBox::RejectRole, it is made the escape button.
    When an escape button could not be automatically detected, pressing Esc has no effect.
    Le souci c'est que dans ton cas de MessageBox on est sur la dernière ligne qui normalement devrait faire No Effect. Mais cela ferme quand même la MessageBox. Par défaut quand on appuie sur un bouton d'une MessageBox cela la ferme.
    J'ai bricolé une sous-classe de MessageBox pour éviter que l'on la ferme quand on appuie sur la touche Esc. Le principe :
    1 - On ajoute un bouton Ignore à la MessageBox et on le cache.
    2 - On désactive les événements sur ce bouton.
    3 - On affecte l'EscapeButton à ce bouton.

    Le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class myMessageBox(QMessageBox):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.addButton(QMessageBox.StandardButton.Ignore)
            self.button(QMessageBox.StandardButton.Ignore).setVisible(False)
            self.button(QMessageBox.StandardButton.Ignore).blockSignals(True)
            self.setEscapeButton(QMessageBox.StandardButton.Ignore)
    L'utilisation :
    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
        def closeEvent(self, event):        print(
                "%s => %s.closeEvent(%s)" % (
                    self.sender().__class__.__name__,
                    self.__class__.__name__,
                    "%s (%s)" % (event.__class__.__name__, type(event)),
                )
            )
            qmesg = myMessageBox(QMessageBox.Question,
                                 "Confirmation",
                                 "Confirmez-vous vouloir quitter ?",
                                 QMessageBox.Yes | QMessageBox.No,
                                 )
            # Question
            reponse = qmesg.exec_()
            if reponse != QMessageBox.Yes:
                event.ignore()
                return
            # if
     
     
            # Appel méthode objet hérité
            super().closeEvent(event)
            event.accept()
    Ami calmant, J.P
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    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 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par jurassic pork Voir le message
    Le souci c'est que dans ton cas de MessageBox on est sur la dernière ligne qui normalement devrait faire No Effect. Mais cela ferme quand même la MessageBox. Par défaut quand on appuie sur un bouton d'une MessageBox cela la ferme.
    J'ai bricolé une sous-classe de MessageBox pour éviter que l'on la ferme quand on appuie sur la touche Esc.
    Super sympa (et bien pensée, je l'ai testée dans mon code). Mais ma question ne portait pas sur l'effet de la touche "esc" à la QMessageBox finale qui demande si on est certain de vouloir quitter mais sur le fait qu'appuyer sur "esc" dans la QDialog principale (celle qui contient le bouton "quit") la fait fermer sans passer par le closeEvent (je n'ai donc même pas la QMessageBox finale).

    Le fait qu'on puisse fermer un QMessageBox par "esc" ne m'embête pas vraiment. Mon souci était dans mes propres widgets que je voulais centraliser toute fermeture (pour libérer des ressources etc) et que dans certain cas je ne passais pas dans le closeEvent.
    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]

  8. #8
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    3 948
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3 948
    Points : 9 276
    Points
    9 276
    Par défaut
    Hello,
    Citation Envoyé par Sve@r Voir le message
    Super sympa (et bien pensée, je l'ai testée dans mon code). Mais ma question ne portait pas sur l'effet de la touche "esc" à la QMessageBox finale qui demande si on est certain de vouloir quitter mais sur le fait qu'appuyer sur "esc" dans la QDialog principale (celle qui contient le bouton "quit") la fait fermer sans passer par le closeEvent (je n'ai donc même pas la QMessageBox finale)
    Sinon pour éviter la fermeture de la QDialog quand on appuie sur la touche Esc, il suffit d' "overrider" la méthode reject :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class myWindow(QDialog):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, *kwargs)
            btn = QPushButton("quit", parent=self, clicked=self.close)
            layout = QHBoxLayout(self)
            layout.addWidget(btn)
     
        def reject(self):
            return
    Ami calmant, J.P
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

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

Discussions similaires

  1. JSF dans du javascript esce possible ?
    Par Mediii dans le forum JSF
    Réponses: 5
    Dernier message: 28/09/2007, 10h20
  2. Inhiber la touche ESC sous 4D 2003
    Par Soun69 dans le forum 4D
    Réponses: 3
    Dernier message: 26/01/2007, 09h36
  3. Differencier esc and quit dans OnCancel
    Par donzagier dans le forum MFC
    Réponses: 1
    Dernier message: 07/12/2006, 22h08
  4. séquence d'échapement dynamique (ESC/POS)
    Par laurentleroy dans le forum C
    Réponses: 1
    Dernier message: 24/05/2006, 13h39
  5. envoyer des codes ESC à une imprimante série sous XP et W98?
    Par rebelor dans le forum API, COM et SDKs
    Réponses: 2
    Dernier message: 14/02/2006, 06h41

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