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 lexemple)
# ------------------------------------------------------------------
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 lutilisateur 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 dexemple
# ------------------------------------------------------------------
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() |
Partager