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 :

[PyQt6] QStyleItemDelegate pour une Combobox ne s'applique qu'a une colonne


Sujet :

PyQt Python

  1. #1
    Membre confirmé Avatar de ptissendier
    Homme Profil pro
    Retraité
    Inscrit en
    Juillet 2011
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Juillet 2011
    Messages : 66
    Par défaut [PyQt6] QStyleItemDelegate pour une Combobox ne s'applique qu'a une colonne
    Bonjour,
    Je voudrais dans un Qtableview pouvoir saisir des données par l'intermediaire d'une combobox
    J'ai trouvé cet exemple.
    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
    from PyQt6.QtWidgets import (
        QItemDelegate,QStyledItemDelegate, QComboBox, QTableView,
        QApplication, QMainWindow,QStyle,QStyleOptionComboBox
    )
    from PyQt6.QtCore import Qt, QModelIndex, QAbstractTableModel, QVariant
     
    # ------------------------------------------------------------------
    # 1.  Modèle simple (pour l’exemple)
    # ------------------------------------------------------------------
    class SimpleModel(QAbstractTableModel):
        def __init__(self, data, headers, parent=None):
            super().__init__(parent)
            self._data = data          # liste de listes
            self._headers = headers
     
        def rowCount(self, parent=QModelIndex()):
            return len(self._data)
     
        def columnCount(self, parent=QModelIndex()):
            return len(self._headers)
     
        def data(self, index, role=Qt.ItemDataRole.DisplayRole):
            if not index.isValid():
                return QVariant()
            if role == Qt.ItemDataRole.DisplayRole:
                return self._data[index.row()][index.column()]
            return QVariant()
     
        def setData(self, index, value, role=Qt.ItemDataRole.EditRole):
            if role == Qt.ItemDataRole.EditRole:
                self._data[index.row()][index.column()] = value
                self.dataChanged.emit(index, index, [role])
                return True
            return False
     
        def flags(self, index):
            return Qt.ItemFlag.ItemIsEditable | Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable
     
        def headerData(self, section, orientation, role=Qt.ItemDataRole.DisplayRole):
            if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
                return self._headers[section]
            return QVariant()
     
    # ------------------------------------------------------------------
    # 2.  Delegate avec ComboBox
    # ------------------------------------------------------------------
    class ComboDelegate(QStyledItemDelegate):
        def __init__(self, items, parent=None):
            super().__init__(parent)
     
            self._items = items          # liste des options du combo
     
        # 2.1  Crée l’éditeur
        def createEditor(self, parent, option, index):
            self.combo = QComboBox(parent)
            self.combo.addItems(self._items)
            # Quand l’utilisateur change la sélection, on force la sauvegarde
            self.combo.currentIndexChanged.connect(
                lambda: self.commitData.emit(self.combo)   # <‑‑ important
            )
            return self.combo
     
        # 2.2  Charge la valeur du modèle dans le combo
        def setEditorData(self, editor, index):
            self.value = index.model().data(index, Qt.ItemDataRole.DisplayRole)
            if self.value in self._items:
                editor.setCurrentIndex(self._items.index(self.value))
            else:
                editor.setCurrentIndex(0)   # valeur par défaut pour les nouvelles lignes
     
        # 2.3  Enregistre la sélection dans le modèle
        def setModelData(self, editor, model, index):
            model.setData(index, editor.currentText(), Qt.ItemDataRole.EditRole)
     
        # 2.4  Positionne l’éditeur dans la cellule
        def updateEditorGeometry(self, editor, option, index):
            editor.setGeometry(option.rect)
     
        def paint(self, painter, option, index):
            #value = index.data(Qt.ItemDataRole.DisplayRole)
            self.style = QApplication.style()
            self.opt = QStyleOptionComboBox()
            #opt.text = str(value)
            self.opt.rect = option.rect
            self.style.drawComplexControl(QStyle.ComplexControl.CC_ComboBox, self.opt, painter)
            QStyledItemDelegate.paint(self, painter, option, index)
     
     
    # ------------------------------------------------------------------
    # 3.  Application d’exemple
    # ------------------------------------------------------------------
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            data = [
                ["Alice", "type_1","A"],
                ["Bob",   "type_2","B"],
            ]
            headers = ["Nom", "Type","Catégorie"]
     
            self.model = SimpleModel(data, headers)
            self.view = QTableView()
            self.view.setModel(self.model)
     
            # Colonne 1 (index 1) devient un combo‑box
            self.view.setItemDelegateForColumn(1, ComboDelegate(["type_1", "type_2", "type_3", "type_4", "type_5"]))
            #self.view.setItemDelegateForColumn(2, ComboDelegate(["A", "B", "C", "D", "E", "F"]))
     
            self.setCentralWidget(self.view)
            self.setWindowTitle("ComboBox dans Items QTableView")
     
    # ------------------------------------------------------------------
    if __name__ == "__main__":
        app = QApplication([])
        win = MainWindow()
        win.resize(400,200)
        win.show()
        app.exec()
    Je n'arrive pas à placer une combo sur la troisième colonne. voir ligne 107. ça plante.
    Je ne comprend pas mon erreur. Peut être vaudrait-il mieux utiliser un QItemDelegate ?
    Quelqu'un peut-il m'aider ?
    Merci

  2. #2
    Expert confirmé

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 311
    Par défaut
    Salut,

    Tu dois d'abord instancier ta comboBox

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    delegate = ComboDelegate([........])
    self.view.setItemDelegateForColumn(1, delegate)
    A tester ....

  3. #3
    Membre confirmé Avatar de ptissendier
    Homme Profil pro
    Retraité
    Inscrit en
    Juillet 2011
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Juillet 2011
    Messages : 66
    Par défaut
    Citation Envoyé par VinsS Voir le message
    Salut,

    Tu dois d'abord instancier ta comboBox

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    delegate = ComboDelegate([........])
    self.view.setItemDelegateForColumn(1, delegate)
    A tester ....
    Merci, j'ai modifié mon code de cette façon
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            self.typeDelegate = ComboDelegate(["type_1", "type_2", "type_3", "type_4", "type_5"])
            self.view.setItemDelegateForColumn(1, self.typeDelegate)
            self.categDelegate =  ComboDelegate(["A", "B", "C", "D", "E", "F"])
            self.view.setItemDelegateForColumn(2,self.categDelegate)
    et .... ça marche. mes deux colonne ont des combobox !

    Par contre je trouve que la "cinématique" ou l'"ergonomie" n'est pas très top.
    Je m'explique ... quand le curseur entre dans la cellule elle se met en surbrillance (comme sélectionnée) la petite flèche de la combo disparait et il faut double cliquer pour voir défiler la combo et faire son choix (c'est un peu fastidieux ).
    Peux tu me donner une piste pour améliorer ce fonctionnement. on clique direct sur la flèche de la cellule et la combo se déroule pour le choix.
    Encore merci pour ton aide.

    Pour la deuxième question ne vaudrait-il mieux pas créer une autre discussion ?

Discussions similaires

  1. Majuscule auto pour une colonne
    Par devdev dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 19/03/2009, 15h23
  2. Police différente pour une colonne d'une ListView
    Par Médinoc dans le forum Windows Forms
    Réponses: 4
    Dernier message: 13/02/2009, 15h28
  3. Largeur fixe pour une colonne de GridView
    Par slokix dans le forum ASP.NET
    Réponses: 11
    Dernier message: 26/09/2007, 09h01
  4. Union de 2 tables pour une colonne
    Par charleshbo dans le forum Langage SQL
    Réponses: 4
    Dernier message: 18/04/2006, 17h23

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