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 :

functools.partial ou QSignalMapper? [QtCore]


Sujet :

PyQt Python

  1. #1
    Membre averti
    Femme Profil pro
    Ingénieur informatique scientifique
    Inscrit en
    mai 2010
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 31
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur informatique scientifique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : mai 2010
    Messages : 313
    Points : 301
    Points
    301
    Par défaut functools.partial ou QSignalMapper?
    Bonjour,

    je développe une IHM qui contient un certain nombre de boutons "parcourir...". Je veux faire la même chose pour chacun de ces boutons: ouvrir un navigateur de fichier, donc appeler la même fonction à chaque fois, avec en argument le nom du widget QPushButton sollicité.

    Pour cela, j'ai utilisé functools.partial, qui fonctionne très bien:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    import functools
    self.ui.bouton1.clicked.connect(functools.partial(self.choisirRepertoire, 'bouton1'))
    self.ui.bouton2.clicked.connect(functools.partial(self.choisirRepertoire, 'bouton2'))
    ...
    Cependant j'ai vu que Qt avait prévu une classe exprès pour ce genre d'application, QSignalMapper.
    Ma première question est: est-ce "propre" d'utiliser functools.partial ou vaut-il mieux utiliser QSignalMapper?

    Ma deuxième question concerne le code que j'ai fait pour tester l'utilisation de QSignalMapper:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    signalMapper = QSignalMapper(self)
    signalMapper.setMapping(self.ui.bouton1, 'bouton1')
    self.ui.bouton1.clicked.connect(signalMapper.map)
    signalMapper.setMapping(self.ui.bouton2, 'bouton2')
    self.ui.bouton2.clicked.connect(signalMapper.map)
    signalMapper.mapped.connect(self.choisirRepertoire)
    Le programme ne réagit plus lorsque j'appuie sur les boutons (la fonction "choisirRepertoire" n'est pas appelée)... Pouvez-vous m'indiquer ce qui est faux dans mon code?

    Merci d'avance.

  2. #2
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    décembre 2007
    Messages
    4 160
    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 160
    Points : 8 633
    Points
    8 633
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Merci d'avoir posé la question! Je n'utilisais jusqu'à présent que partial.

    Voilà 2 codes simples avec les 2 solutions (Python 2.7, PyQt4).

    Solution avec partial:

    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    from __future__ import division
    # Python 2.7
     
    import sys
     
    from functools import partial
     
    from PyQt4 import QtCore, QtGui
     
    #############################################################################
    class Fenetre(QtGui.QWidget):
     
        def __init__(self, parent=None):
            super(Fenetre, self).__init__(parent)
     
            self.bouton1 = QtGui.QPushButton(u"bouton 1", self)
            self.bouton1.clicked.connect(partial(self.choisirRepertoire, 1))     
     
            self.bouton2 = QtGui.QPushButton(u"bouton 2", self)
            self.bouton2.clicked.connect(partial(self.choisirRepertoire, 2))     
     
            posit = QtGui.QGridLayout()
            posit.addWidget(self.bouton1, 0, 0)
            posit.addWidget(self.bouton2, 1, 0)
            self.setLayout(posit)
     
        def choisirRepertoire(self, num):
            QtGui.QMessageBox.information(self,
                u"Bouton cliqué",
                u"c'est le bouton %s" % num)
     
    #############################################################################
    if __name__ == "__main__":
        app = QtGui.QApplication(sys.argv)
        fen = Fenetre()
        fen.show()
        sys.exit(app.exec_())
    Solution avec QSignalMapper:

    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    from __future__ import division
    # Python 2.7
     
    import sys
     
    from PyQt4 import QtCore, QtGui
     
    #############################################################################
    class Fenetre(QtGui.QWidget):
     
        def __init__(self, parent=None):
            super(Fenetre, self).__init__(parent)
     
            self.bouton1 = QtGui.QPushButton(u"bouton 1", self)
            self.bouton2 = QtGui.QPushButton(u"bouton 2", self)
     
            signalMapper = QtCore.QSignalMapper(self)
     
            signalMapper.setMapping(self.bouton1, 1)
            self.bouton1.clicked.connect(signalMapper.map)
     
            signalMapper.setMapping(self.bouton2, 2)
            self.bouton2.clicked.connect(signalMapper.map)
     
            signalMapper.mapped.connect(self.choisirRepertoire)
     
            posit = QtGui.QGridLayout()
            posit.addWidget(self.bouton1, 0, 0)
            posit.addWidget(self.bouton2, 1, 0)
            self.setLayout(posit)
     
        def choisirRepertoire(self, num):
            QtGui.QMessageBox.information(self,
                u"Bouton cliqué",
                u"c'est le bouton %s" % num)
     
    #############################################################################
    if __name__ == "__main__":
        app = QtGui.QApplication(sys.argv)
        fen = Fenetre()
        fen.show()
        sys.exit(app.exec_())
    Quelle solution faut-il choisir? J'ai une légère tendance à utiliser la solution Qt quand elle existe, et c'est ce qui me fait préférer, par exemple, QThread à threading, avec dans ce cas l'avantage de pouvoir émettre des signaux en direction de la fenêtre. Mais, pour l'utiliser souvent, je constate que partial fonctionne parfaitement sous PyQt4.
    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
    Membre averti
    Femme Profil pro
    Ingénieur informatique scientifique
    Inscrit en
    mai 2010
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 31
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur informatique scientifique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : mai 2010
    Messages : 313
    Points : 301
    Points
    301
    Par défaut
    Merci pour tes exemples de code, mon erreur venait du fait que je spécifiais les "setMapping" avant de connecter mes boutons au signal clicked(). Voici mon code corrigé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    signalMapper = QSignalMapper(self)
    self.ui.bouton1.clicked.connect(signalMapper.map)
    signalMapper.setMapping(self.ui.bouton1, 'bouton1')
    self.ui.bouton2.clicked.connect(signalMapper.map)
    signalMapper.setMapping(self.ui.bouton2, 'bouton2')
    signalMapper.mapped[str].connect(self.choisirRepertoire)
    Merci!
    Au final je pense que je vais préférer cette solution plutôt que d'uitliser functools.partial.

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

Discussions similaires

  1. Ajout dynamique de méthode et functools.partial
    Par Alexis.M dans le forum Général Python
    Réponses: 3
    Dernier message: 12/02/2014, 14h04
  2. Réponses: 4
    Dernier message: 22/06/2007, 18h02
  3. probleme avec partiaL class
    Par jul-974 dans le forum Framework .NET
    Réponses: 2
    Dernier message: 03/11/2006, 06h00
  4. Partial update, et grooooosse combo list
    Par johan_barbier dans le forum XMLRAD
    Réponses: 7
    Dernier message: 19/10/2005, 17h40

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