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 :

[QCombobox] Remplissage en cascade [QtGui]


Sujet :

PyQt Python

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut [QCombobox] Remplissage en cascade
    Bonjour à tous,
    J'ai deux QCombobox et un dictionnaire de dictionnaires pour mimer une arborescence.
    La première combobox,combo1, contient "des enfants" et je voudrais que la deuxième combobox, combo2, contienne "les petits enfants".
    Pour initialiser, ça va. Mais je n'arrive pas à rafraichir le contenu de combo2 quand celui de combo1 change.
    Voici le code:
    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
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    """
    ZetCode PyQt4 tutorial 
     
    This example shows
    how to use QtGui.QComboBox widget.
     
    author: Jan Bodnar
    website: zetcode.com 
    last edited: September 2011
     
    Modif
    author: Jean-Patrick Pommier
    website: dip4fish.blogspot.com 
    last edited: March 2012
     
    Given a tree like structure : dic={"p1":{"s1":5,"s2":7},"p2":{"s3":1,"s4":2}}
    if p1 is selected in combo1 then combo2 should be filled with: s1, s2
       p2 -------------------------------------------------------: s3, s4
     
    """
     
    import sys
    from PyQt4 import QtGui, QtCore
     
    class CascadeMenu(QtGui.QWidget):
     
        def __init__(self,dico):
            super(CascadeMenu, self).__init__()
            #print dico.keys()
            self.initUI(dico)
     
        def initUI(self,dico):      
            print dico.keys()
            self.lbl = QtGui.QLabel("CytoM", self)
            #self.fullpath should be first element of menu1 / first elem of menu2
            self.fullpath=QtGui.QLabel("path", self)
     
            combo1 = QtGui.QComboBox(self)
            for entry in dico.keys():
                print entry
                combo1.addItem(entry)
            #Find visible entry (first element) in combo1
    #        print "first combo1 item",combo1.itemText(0)
    #        print "type",type(combo1.itemText(0))
    #        print str(combo1.itemText(0))
    #        print "set 1st item in second menu",dico.get(str(combo1.itemText(0)))
            combo2=QtGui.QComboBox(self)
            for entry in dico.get(str(combo1.itemText(0))):
                print entry
                combo2.addItem(entry)
     
            combo1.move(50, 50)
            combo2.move(100, 50)
            #combo1.
            self.lbl.move(50, 150)
     
            #Signal -> Slot 
            combo1.activated[str].connect(self.onActivated)
     
            # let's try that
            combo2.activated[str].connect(self.onActivated)
     
            self.setGeometry(300, 300, 300, 200)
            self.setWindowTitle('Cascade Menus')
            self.show()
     
        def fillNextCombo(self,previouscombo):
            pass
     
        def onActivated(self, text):
            print text#how 'text' is build?
            self.fullpath.setText("should be menu1/menu2") 
            self.fullpath.adjustSize()  
            self.lbl.setText(text)
            self.lbl.adjustSize()  
     
    def main():
        print 
        app = QtGui.QApplication(sys.argv)
        dic={"p1":{"s1":5,"s2":7},"p2":{"s3":1,"s4":2}}
        ex = CascadeMenu(dic)
        sys.exit(app.exec_())
     
    if __name__ == '__main__':
        main()
    J'ai déjà vu une question à ce sujet. Je vois bien qu'il y a un problème signal/slot, mais débutant avec pyQt4 je ne comprend pas la réponse.
    Comment corriger le code pour que cela fonctionne?
    Merci d'avance.
    Jean-Patrick Pommier

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

    Le principe est simple: il faut utiliser le signal 'currentIndexChanged(int)' qui est généré quand l'affichage du combobox change, et qui lance la méthode désigné avec en argument le nouvel index affiché.

    Par exemple:

    Dans la construction du combo1, on veut que le signal lance la méthode changeindexcombo1:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.connect(self.combo1, QtCore.SIGNAL('currentIndexChanged(int)'), self.changeindexcombo1)
    Et la méthode lancée:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def changeindexcombo1(self, index):
        ...
        ...
    Cette méthode connaissant l'index affiché sur combo1, peut en déduire ce qu'il faut afficher sur combo2: effacer son contenu et le remplacer par la nouvelle liste adaptée à l'index de combo1.

    Par exemple index=3 sur combo1 => liste3 sur combo2:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    self.combo2.clear()
    if index==3:
        self.combo2.addItems(QtCore.QStringList(self.liste3))
    Ok?
    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

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Salut,

    Un exemple en reprenant le tien:
    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
     
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    import sys
    from PyQt4 import QtGui, QtCore
     
    class CascadeMenu(QtGui.QWidget):
     
        def __init__(self,dico):
            super(CascadeMenu, self).__init__()
            self.dico = dico
            self.initUI(dico)
     
        def initUI(self,dico):      
            print dico.keys()
            self.lbl = QtGui.QLabel("CytoM", self)
            self.fullpath = QtGui.QLabel("path", self)
            self.combo1 = QtGui.QComboBox(self)
            self.combo1.addItems(dico.keys())
            self.combo2 = QtGui.QComboBox(self)
            self.populate_combo()
            self.combo1.move(50, 50)
            self.combo2.move(150, 50)
            self.lbl.move(50, 150)
            self.combo1.currentIndexChanged.connect(self.populate_combo)
            self.combo2.activated.connect(self.onActivated)
            self.setGeometry(300, 300, 300, 200)
            self.setWindowTitle('Cascade Menus')
            self.show()
     
        def onActivated(self, val):
            key = str(self.combo1.currentText())
            subkey = str(self.combo2.currentText())  
            self.lbl.setText("Key: {0}, SubKey: {1}, val: {2}".format
                                (key, subkey, self.dico[key][subkey]))
            self.lbl.adjustSize() 
     
        def populate_combo(self, arg=None):
            self.combo2.clear()
            self.combo2.addItems(self.dico[str(self.combo1.currentText())].keys())
            if arg is not None:
                 self.onActivated(self.combo1.currentText())
     
    def main():
        print 
        app = QtGui.QApplication(sys.argv)
        dic={"Key1":{"SubKey1":5,"SubKey2":7},"Key2":{"SubKey3":1,"SubKey4":2}}
        ex = CascadeMenu(dic)
        sys.exit(app.exec_())
     
    if __name__ == '__main__':
        main()
    Par contre le '[str]' ne devrait pas être là:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    combo1.activated[str].connect(self.onActivated)

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Bonjour,
    Merci pour votre aide.
    Est-ce que la méthode
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    changeIndexCombo1(self, index)
    est un slot de combo2?
    C'est pas encore ok, mais ça progresse.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Merci bien,
    ça fonctionne, reste à re-relire la doc/tuto signaux pour arriver à 4 combo box.

    Citation Envoyé par VinsS Voir le message
    Salut,

    Un exemple en reprenant le tien:
    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
     
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    import sys
    from PyQt4 import QtGui, QtCore
     
    class CascadeMenu(QtGui.QWidget):
     
        def __init__(self,dico):
            super(CascadeMenu, self).__init__()
            self.dico = dico
            self.initUI(dico)
     
        def initUI(self,dico):      
            print dico.keys()
            self.lbl = QtGui.QLabel("CytoM", self)
            self.fullpath = QtGui.QLabel("path", self)
            self.combo1 = QtGui.QComboBox(self)
            self.combo1.addItems(dico.keys())
            self.combo2 = QtGui.QComboBox(self)
            self.populate_combo()
            self.combo1.move(50, 50)
            self.combo2.move(150, 50)
            self.lbl.move(50, 150)
            self.combo1.currentIndexChanged.connect(self.populate_combo)
            self.combo2.activated.connect(self.onActivated)
            self.setGeometry(300, 300, 300, 200)
            self.setWindowTitle('Cascade Menus')
            self.show()
     
        def onActivated(self, val):
            key = str(self.combo1.currentText())
            subkey = str(self.combo2.currentText())  
            self.lbl.setText("Key: {0}, SubKey: {1}, val: {2}".format
                                (key, subkey, self.dico[key][subkey]))
            self.lbl.adjustSize() 
     
        def populate_combo(self, arg=None):
            self.combo2.clear()
            self.combo2.addItems(self.dico[str(self.combo1.currentText())].keys())
            if arg is not None:
                 self.onActivated(self.combo1.currentText())
     
    def main():
        print 
        app = QtGui.QApplication(sys.argv)
        dic={"Key1":{"SubKey1":5,"SubKey2":7},"Key2":{"SubKey3":1,"SubKey4":2}}
        ex = CascadeMenu(dic)
        sys.exit(app.exec_())
     
    if __name__ == '__main__':
        main()
    Par contre le '[str]' ne devrait pas être là:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    combo1.activated[str].connect(self.onActivated)
    C'est le reste d'un code que j'ai modifié et je n'avais pas trop cherché à comprendre ce point.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Bonjour,
    Je me demande si je dois construire index à partir du combo1 ou du dictionnaire pour construire ensuite self.liste3.
    Citation Envoyé par tyrtamos Voir le message

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def changeindexcombo1(self, index):
        ...
        ...
    Cette méthode connaissant l'index affiché sur combo1, peut en déduire ce qu'il faut afficher sur combo2: effacer son contenu et le remplacer par la nouvelle liste adaptée à l'index de combo1.

    Par exemple index=3 sur combo1 => liste3 sur combo2:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    self.combo2.clear()
    if index==3:
        self.combo2.addItems(QtCore.QStringList(self.liste3))
    Ok?
    merci

  7. #7
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Citation Envoyé par jean-pat Voir le message
    Est-ce que la méthode
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    changeIndexCombo1(self, index)
    est un slot de combo2?
    Non, de combo1
    Citation Envoyé par tyrtamos
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.connect(self.combo1, QtCore.SIGNAL('currentIndexChanged(int)'), self.changeindexcombo1)
    Citation Envoyé par jean-pat
    Je me demande si je dois construire index à partir du combo1 ou du dictionnaire pour construire ensuite self.liste3.
    Tu dois surtout prendre en compte que les dictionnaires ne sont pas ordonnés. Donc l'ordre des items dans les combos sera celui dans lequel python te retourne la liste des clés du dico.

    En général on préfèrera un ordre adapté au type de valeur, ordre alphabétique pour le confort de l'utilisateur, ordre de grandeur de valeur pour des raisons de cohérence, etc.

    Donc, comme le suggère Tyrtamos, crées d'abord une liste d'items à partir du dico et que tu tries dans l'ordre nécessaire, après, tu pourras te référer à l'index courant du comboBox pour connaitre la valeur affichée sans devoir faire à chaque fois une comparaison avec 'str(combo.currentText())', ce qui n'est pas très rationnel,surtout si tu comptes multiplier les comboBox et les faire interagir entre eux.

    Ici, tu trouveras quantité d'exemples PyQt:
    http://diotavelli.net/PyQtWiki/SampleCode

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

    Il y a un choix à faire sur le type de données qu'on manipule (listes ou dictionnaires), mais dans tous les cas, il faut pouvoir en déduire la liste à introduire dans chacun des combobox en fonction de l'affichage du précédent.

    Voilà 2 exemples possibles en fonction du signal émis, puisque ce signal peut transmettre l'index affiché (signal par défaut) ou le texte affiché:

    1er exemple: le signal envoie l'index du texte affiché:

    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    # 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.combo1 = QtGui.QComboBox(self)
            self.list1 = ['x', 'y', 'z']
            self.combo1.addItems(QtCore.QStringList(self.list1))
            # les 2 lignes suivantes donnent le même résultat parce que la transmission de l'index est le signal par défaut
            #self.connect(self.combo1, QtCore.SIGNAL('currentIndexChanged(int)'), self.changeindexcombo1)
            self.combo1.currentIndexChanged.connect(self.changeindexcombo1)
     
     
            self.combo2 = QtGui.QComboBox(self)
            self.list2 = [['x1', 'x2', 'x3'],['y1', 'y2', 'y3'],['z1', 'z2', 'z3']]
            self.combo2.addItems(QtCore.QStringList(self.list2[0]))
     
            # positionnement des widgets dans la fenêtre
            posit = QtGui.QGridLayout()
            posit.addWidget(self.combo1, 0, 0)
            posit.addWidget(self.combo2, 0, 1)
            self.setLayout(posit)
     
        def changeindexcombo1(self, ind):
            """méthode exécutée en cas de changement d'affichage du combo1
               ind est le nouvel index du texte affiché
            """
            self.combo2.clear()
            self.combo2.addItems(QtCore.QStringList(self.list2[ind]))
     
    if __name__ == "__main__":
        app = QtGui.QApplication(sys.argv)
        fen = Fenetre()
        fen.show()
        sys.exit(app.exec_())
    2e exemple: le signal envoie le texte affiché. Dans ce cas, les données peuvent être sous forme de dictionnaires, avec pour clés les textes affichés dans le combo précédent:

    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    # 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.combo1 = QtGui.QComboBox(self)
            self.list1 = ['x', 'y', 'z']
            self.combo1.addItems(QtCore.QStringList(self.list1))
            # il faut utiliser cette forme pour passer le texte affiché et non son index:
            self.connect(self.combo1, QtCore.SIGNAL('currentIndexChanged(QString)'), self.changeindexcombo1)
     
     
            self.combo2 = QtGui.QComboBox(self)
            self.list2 = {'x': ['x1', 'x2', 'x3'],'y': ['y1', 'y2', 'y3'],'z': ['z1', 'z2', 'z3']}
            self.combo2.addItems(QtCore.QStringList(self.list2[self.list1[0]]))
     
            # positionnement des widgets dans la fenêtre
            posit = QtGui.QGridLayout()
            posit.addWidget(self.combo1, 0, 0)
            posit.addWidget(self.combo2, 0, 1)
            self.setLayout(posit)
     
        def changeindexcombo1(self, item1):
            """méthode exécutée en cas de changement d'affichage du combo1
               item est le nouveau texte affiché
            """
            self.combo2.clear()
            self.combo2.addItems(QtCore.QStringList(self.list2[unicode(item1)]))
     
    if __name__ == "__main__":
        app = QtGui.QApplication(sys.argv)
        fen = Fenetre()
        fen.show()
        sys.exit(app.exec_())
    Je n'ai pas eu le courage de créer toutes les listes pour 4 combos: avec 3 items par combo, il faut 9 listes pour le 3e et 27 pour le 4e...

    [edit] comme le dit VinsS, si on utilise un dictionnaire, il faut l'appeler par clé et non par index, puisque l'ordre des clés n'est pas conservé. Ou alors, il faut utiliser un dictionnaire qui conserve l'ordre (ex: OrderedDict du module collections).
    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

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Bonjour,

    Il y a un choix à faire sur le type de données qu'on manipule (listes ou dictionnaires), mais dans tous les cas, il faut pouvoir en déduire la liste à introduire dans chacun des combobox en fonction de l'affichage du précédent.
    En fait, j'espère pouvoir utiliser un fichier xml
    Citation Envoyé par tyrtamos Voir le message
    Je n'ai pas eu le courage de créer toutes les listes pour 4 combos: avec 3 items par combo, il faut 9 listes pour le 3e et 27 pour le 4e...
    C'est déjà énorme de proposer deux solutions.
    Citation Envoyé par tyrtamos Voir le message
    [edit] comme le dit VinsS, si on utilise un dictionnaire, il faut l'appeler par clé et non par index, puisque l'ordre des clés n'est pas conservé. Ou alors, il faut utiliser un dictionnaire qui conserve l'ordre (ex: OrderedDict du module collections).
    J'espère pouvoir peupler les combobox , avec les différents "étages" du fichier xml. Le but étant d'écrire un navigateur d'images stockées de manière hierachique.

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Citation Envoyé par VinsS Voir le message
    Non, de combo1
    Je pensais que la syntaxe était:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.connect(widget_emetteur,SIGNAL("...."),widget_recepteur,SLOT("...."))
    et que donc combo1 était l'émetteur et combo2 le recepteur et ainsi la dernière fonctio/méthode représentait le slot...
    Citation Envoyé par VinsS Voir le message
    Tu dois surtout prendre en compte que les dictionnaires ne sont pas ordonnés. Donc l'ordre des items dans les combos sera celui dans lequel python te retourne la liste des clés du dico.

    En général on préfèrera un ordre adapté au type de valeur, ordre alphabétique pour le confort de l'utilisateur, ordre de grandeur de valeur pour des raisons de cohérence, etc.

    Donc, comme le suggère Tyrtamos, crées d'abord une liste d'items à partir du dico et que tu tries dans l'ordre nécessaire, après, tu pourras te référer à l'index courant du comboBox pour connaitre la valeur affichée sans devoir faire à chaque fois une comparaison avec 'str(combo.currentText())', ce qui n'est pas très rationnel,surtout si tu comptes multiplier les comboBox et les faire interagir entre eux.
    ok
    Citation Envoyé par VinsS Voir le message
    Ici, tu trouveras quantité d'exemples PyQt:
    http://diotavelli.net/PyQtWiki/SampleCode
    merci

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Bon,
    Je pense que le code suivant fonctionne à peu près correctement quant à la navigation. Le chemin indiqué dans le message n'est pas encore correct.

    Ce code permet de naviguer dans une arborescence stockée dans un fichier xml gérer avec lxml.
    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
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
     
    # -*- coding: utf-8 -*-
    """
    Created on Fri Mar 30 10:42:54 2012
     
    @author: JeanPat
    """
    import sys
    import lxml.etree as et
    from copy import deepcopy
    from PyQt4 import QtGui, QtCore
     
     
    def GetChidrenName(etree):
            """return the names (str) of the children of an Database etree.Element"""
            childrenlist=[]
            print "GetChildren ... type(etree)",type(etree[0])
            children=etree.getchildren()
            print children[0].get("name")
            for c in children:
                childrenlist.append(c.get("name"))
            return childrenlist
     
    class CascadeMenu(QtGui.QWidget):
        """Four combobox to explore a tree content"""
        def __init__(self,etree):
            super(CascadeMenu, self).__init__()
            self.db = etree#DataBase:The whole directory tree 
     
            self.lbl = QtGui.QLabel("CytoM", self)
     
    #==============================================================================
    #         Connection en cascade des QCombobox
    #==============================================================================
     
            ##Connection combo1 vers combo2
            self.combo1 = QtGui.QComboBox(self)#projects list
            self.label_combo1 = QtGui.QLabel("Project",self)
            #self.combo1.addWidget(self.label_combo1)
            self.connect(self.combo1, QtCore.SIGNAL('currentIndexChanged(QString)'),\
                                        self.changeindexcombo1)
            ##Connection combo2 vers combo3
            self.combo2 = QtGui.QComboBox(self)#slides list
            self.label_combo2 = QtGui.QLabel("Slide",self)
            self.connect(self.combo2, QtCore.SIGNAL('currentIndexChanged(QString)'),\
                                        self.changeindexcombo2)
            ##Connection combo3 vers combo4                            
            self.combo3 = QtGui.QComboBox(self)#fields list
            self.label_combo3 = QtGui.QLabel("Field",self)
            self.connect(self.combo3, QtCore.SIGNAL('currentIndexChanged(QString)'),\
                                        self.changeindexcombo3)
            ##Connection combo4 vers combo5; appel de chargement d'un fluo                                      
            self.combo4 = QtGui.QComboBox(self)#Fluorochromes list
            self.label_combo4 = QtGui.QLabel("Fluo",self)
            self.connect(self.combo4, QtCore.SIGNAL('currentIndexChanged(QString)'),\
                                        self.changeindexcombo4)
            ##Connection combo5 vers : appel d'une image                                     
            self.combo5 = QtGui.QComboBox(self)#Fluorochromes list
            self.label_combo5 = QtGui.QLabel("Image",self)
            self.connect(self.combo5, QtCore.SIGNAL('currentIndexChanged(QString)'),\
                                        self.changeindexcombo5)
     
            # positionnement des widgets dans la fenêtre
            posit = QtGui.QGridLayout()
            posit.addWidget(self.label_combo1, 0, 0)
            posit.addWidget(self.label_combo2, 0, 1)
            posit.addWidget(self.label_combo3, 0, 2)
            posit.addWidget(self.label_combo4, 0, 3)
            posit.addWidget(self.label_combo5, 0, 4)
            posit.addWidget(self.combo1, 1, 0)
            posit.addWidget(self.combo2, 1, 1)
            posit.addWidget(self.combo3, 1, 2)
            posit.addWidget(self.combo4, 1, 3)
            posit.addWidget(self.combo5, 1, 4)
            posit.addWidget(self.lbl, 2, 0)
            self.setLayout(posit)
            self.setWindowTitle('Cascade Menus')
            self.show()
     
    #==============================================================================
    #         Fill combo1 with projects list
    #==============================================================================
            #Combo1: first level in the tree
            self.combo1.addItems(GetChidrenName(self.db))#project level-first element
            self.node1=self.db.getchildren()
    #==============================================================================
    #         Fill combo2 with slides belonging to a project 
    #==============================================================================
            self.node2=None          #slide level
            self.node2=self.node1[0].getchildren()        
            #fill from combo1 active item as parent
            #
            parent=self.node1[self.combo1.currentIndex()]
            childrenlist=GetChidrenName(parent)
            print "init combo2 :childrenlist",childrenlist
            self.combo2.addItems(QtCore.QStringList(childrenlist))
    #==============================================================================
    #         Fill combo3 with fields (metaphases) of a given slide
    #==============================================================================
            self.node3=None                #field level
            self.node3=self.node2[0].getchildren()
            parent=self.node2[self.combo2.currentIndex()]
            childrenlist=GetChidrenName(parent)
            print "init combo3 :childrenlist",childrenlist
            self.combo3.addItems(QtCore.QStringList(childrenlist))
    #==============================================================================
    #         Fill combo4 with Fluo ("color"DAPI,...) of a field
    #==============================================================================
            self.node4=None                #fluo level
            self.node4=self.node3[0].getchildren()
            print "init node4",self.node4
            parent=self.node3[self.combo3.currentIndex()]
            childrenlist=GetChidrenName(parent)
            self.combo4.addItems(QtCore.QStringList(childrenlist))
    #==============================================================================
    #         Fill combo5 with image(s) of a fluorochrome
    #==============================================================================
            self.node5=None                #fluo level
            self.node5=self.node4[0].getchildren()
            parent=self.node4[self.combo4.currentIndex()]
            childrenlist=GetChidrenName(parent)
            self.combo5.addItems(QtCore.QStringList(childrenlist))
     
    #==============================================================================
    #         test
    #==============================================================================
            print "node1",type(self.node1),self.node1
     
     
     
        def GetChidrenName(etree):
            """return the names (str) of the children of an Database etree.Element"""
            childrenlist=[]
            children=etree.getchildren()#list of etree chidren
            for c in children:
                childrenlist.append(c.get("name"))
            return childrenlist
     
        def changeindexcombo1(self):
            """méthode exécutée en cas de changement d'affichage du combo1
            """
            text=str(self.combo1.currentText())+"/"+str(self.combo2.currentText())
            self.lbl.setText(text)
            self.combo2.clear()
            #quel le parent?
            #recup l'item actif de combo1
            print "combo1 cur Index",self.combo1.currentIndex()
            #identifier le node correspondant,
            ## suppossons que ce soit==self.combo1.currentIndex()
            ##parent est un etree.Element, son nom devrait être l'item courant de combo1
            parent=self.node1[self.combo1.currentIndex()]
            #demander ses enfants,
            ##demander le nom des enfants
            childrenlist=GetChidrenName(parent)
            self.combo2.addItems(QtCore.QStringList(childrenlist))
     
        def changeindexcombo2(self):
            """méthode exécutée en cas de changement d'affichage du combo2
            """
            text=str(self.combo1.currentText())+"/"+str(self.combo2.currentText())
            self.lbl.setText(text)
            self.combo3.clear()
            #quel le parent?
            #recup l'item actif de combo1
            print "combo2 cur Index",self.combo2.currentIndex()
            #identifier le node correspondant,
            ## suppossons que ce soit==self.combo1.currentIndex()
            ##parent est un etree.Element, son nom devrait être l'item courant de combo1
            parent=self.node2[self.combo2.currentIndex()]
            #demander ses enfants,
            ##demander le nom des enfants
            childrenlist=GetChidrenName(parent)
            self.combo3.addItems(QtCore.QStringList(childrenlist))
     
        def changeindexcombo3(self):
            """méthode exécutée en cas de changement d'affichage du combo3
            """
            text=str(self.combo1.currentText())+"/"+\
                 str(self.combo2.currentText())+"/"+\
                 str(self.combo3.currentText())+"/"+\
                 str(self.combo4.currentText())
            self.lbl.setText(text)
            self.combo4.clear()
            #quel le parent?
            #recup l'item actif de combo1
            print "combo3 cur Index",self.combo3.currentIndex()
            #identifier le node correspondant,
            ## suppossons que ce soit==self.combo1.currentIndex()
            ##parent est un etree.Element, son nom devrait être l'item courant de combo1
            parent=self.node3[self.combo3.currentIndex()]
            #demander ses enfants,
            ##demander le nom des enfants
            childrenlist=GetChidrenName(parent)
            self.combo4.addItems(QtCore.QStringList(childrenlist))
     
        def changeindexcombo4(self):
            """méthode exécutée en cas de changement d'affichage du combo4
            """
            text=str(self.combo1.currentText())+"/"+\
                 str(self.combo2.currentText())+"/"+\
                 str(self.combo3.currentText())+"/"+\
            self.lbl.setText(text)
            self.combo5.clear()
            #quel le parent?
            #recup l'item actif de combo1
            print "combo4 cur Index",self.combo4.currentIndex()
            #identifier le node correspondant,
            ## suppossons que ce soit==self.combo1.currentIndex()
            ##parent est un etree.Element, son nom devrait être l'item courant de combo1
            parent=self.node4[self.combo4.currentIndex()]
            #demander ses enfants,
            ##demander le nom des enfants
            childrenlist=GetChidrenName(parent)
            self.combo5.addItems(QtCore.QStringList(childrenlist))
     
        def changeindexcombo5(self):
            text=str(self.combo1.currentText())+"/"+\
                 str(self.combo2.currentText())+"/"+\
                 str(self.combo3.currentText())+"/"+\
            self.lbl.setText(text)
            #self.combo5.clear()
            #quel le parent?
            #recup l'item actif de combo4
            print "combo4 cur Index",self.combo4.currentIndex()
            #identifier le node correspondant,
            ## suppossons que ce soit==self.combo1.currentIndex()
            ##parent est un etree.Element, son nom devrait être l'item courant de combo1
            parent=self.node4[self.combo4.currentIndex()]
            #demander ses enfants,
            ##demander le nom des enfants
            childrenlist=GetChidrenName(parent)
            self.combo5.addItems(QtCore.QStringList(childrenlist))
     
    def main():
    #==============================================================================
    #     Build a xml tree
    #==============================================================================
        R=et.Element('racine')
        a=et.Element('project',name='applied')
        R.append(a)
        v=et.Element('project',name='vysis')
        R.append(v)
     
        s1=et.Element('slide',name='s1')
        s2=et.Element('slide',name='s2')
        a.append(s1)
        a.append(s2)
        sprime1=et.Element('slide',name='slide0')
        v.append(sprime1)
        a.set("path","/path/to/project")
        v.set("path","/path/to/project") 
     
        f1=et.Element('field',name='metaphase 1')
        f2=et.Element('field',name='metaphase 2')
        f3=et.Element('field',name='nuclei 1')
        sprime1.append(deepcopy(f3))
        sprime1.append(deepcopy(f2))
     
        fluo0=et.Element('fluo',name='IP')
        fluo1=et.Element('fluo',name='DAPI')
        fluo2=et.Element('fluo',name='Cy3')
        fluo3=et.Element('fluo',name='FITC')
     
        im1=et.Element('image',name='1',ext='.TIF')
     
        fluo1.append(deepcopy(im1))
        fluo2.append(deepcopy(im1))
     
        f1.append(deepcopy(fluo1))
        f1.append(deepcopy(fluo2))
        s1.append(deepcopy(f1))
        s1.append(deepcopy(f2))
        s2.append(deepcopy(f1))
        print(et.tostring(R,pretty_print=True))
     
     
    #==============================================================================
    #     
    #==============================================================================
        app = QtGui.QApplication(sys.argv)
        ex = CascadeMenu(R)
        sys.exit(app.exec_())
     
    if __name__ == '__main__':
        main()

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    voila à quoi ce ressemble en action

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

Discussions similaires

  1. Remplissage de QComboBox
    Par mosflex dans le forum Débuter
    Réponses: 2
    Dernier message: 05/03/2012, 23h47
  2. Remplissage de QComboBox depuis une requête SQL
    Par L0101SA dans le forum Bases de données
    Réponses: 2
    Dernier message: 01/03/2008, 20h42
  3. Delete on cascade avec SQL server
    Par fadoua dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 14/01/2004, 11h02
  4. Réponses: 13
    Dernier message: 14/10/2003, 14h31
  5. Réponses: 11
    Dernier message: 04/08/2003, 15h30

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