PyQt - Comment la QComboBox dans un affichage tableau à l'aide de QItemDelegate
J'essaie d'afficher une zone de liste modifiable dans ma table, de sorte que je peux mettre à l'index sélectionné à partir du modèle de table, comme les autres cellules du tableau. J'ai reconstitué cette ensemble à partir d'autres exemples, mais ne peut toujours pas comprendre comment l'interaction contribue à l'index sélectionné de la QComboBox.
C'est l'exemple le plus simple que je peux venir avec pour démontrer le problème. Si quelqu'un peut le démontrer comment définir l'index automatiquement à partir du modèle de données? Aussi comment utiliser le " currentIndexChanged signal, comme cela semble le feu presque continuellement, à chaque fois qu'il est repeint? Merci.
# The following tells SIP (the system that binds Qt's C++ to Python)
# to return Python native types rather than QString and QVariant
import sip
sip.setapi('QString', 2)
sip.setapi('QVariant', 2)
from PyQt4 import QtCore, QtGui
class TableModel(QtCore.QAbstractTableModel):
"""
A simple 5x4 table model to demonstrate the delegates
"""
def rowCount(self, parent=QtCore.QModelIndex()): return 5
def columnCount(self, parent=QtCore.QModelIndex()): return 4
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid(): return None
if not role==QtCore.Qt.DisplayRole: return None
return "{0:02d}".format(index.row())
class ComboDelegate(QtGui.QItemDelegate):
"""
A delegate that places a fully functioning QComboBox in every
cell of the column to which it's applied
"""
def __init__(self, parent):
QtGui.QItemDelegate.__init__(self, parent)
def paint(self, painter, option, index):
self.combo = QtGui.QComboBox(self.parent())
self.connect(self.combo, QtCore.SIGNAL("currentIndexChanged(int)"), self.parent().currentIndexChanged)
li = []
li.append("Zero")
li.append("One")
li.append("Two")
li.append("Three")
li.append("Four")
li.append("Five")
self.combo.addItems(li)
if not self.parent().indexWidget(index):
self.parent().setIndexWidget(
index,
self.combo
)
class TableView(QtGui.QTableView):
"""
A simple table to demonstrate the QComboBox delegate.
"""
def __init__(self, *args, **kwargs):
QtGui.QTableView.__init__(self, *args, **kwargs)
# Set the delegate for column 0 of our table
# self.setItemDelegateForColumn(0, ButtonDelegate(self))
self.setItemDelegateForColumn(0, ComboDelegate(self))
@QtCore.pyqtSlot()
def currentIndexChanged(self, ind):
print "Combo Index changed {0} {1} : {2}".format(ind, self.sender().currentIndex(), self.sender().currentText())
if __name__=="__main__":
from sys import argv, exit
class Widget(QtGui.QWidget):
"""
A simple test widget to contain and own the model and table.
"""
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
l=QtGui.QVBoxLayout(self)
self._tm=TableModel(self)
self._tv=TableView(self)
self._tv.setModel(self._tm)
l.addWidget(self._tv)
a=QtGui.QApplication(argv)
w=Widget()
w.show()
w.raise_()
exit(a.exec_())
Vous devez vous connecter pour publier un commentaire.
Vous utilisez
paint
méthode incorrecte. Il doit être utilisé lorsque vous souhaitez modifier l'affichage de comportement de la vue. Aussi la création de nouveaux widget à chaque fois que vous voulez peindre, il est très coûteux. Mais vous voulez modifier le comportement d'édition si vous avez besoin de changer toute la logique de votre programme.Voir le code fixe. Ci-dessous je vais expain les modifications.
1.
Tout d'abord, nous avons besoin de faire la première colonne modifiable. Vous pouvez le faire en réimplanterQAbstractItemModel::flags
:2.
Par défaut, l'éditeur de l'élément est créé lorsque l'utilisateur effectue un double-clic sur l'élément. Si vous souhaitez afficher toutes les zones de liste modifiables par défaut, vous pouvez utiliseropenPersistentEditor
:Notez que vous devez également ouvrir les éditeurs pour de nouvelles cellules (le cas échéant).
3.
Maintenant, revenons à notre délégué. Nous avons besoin de mettre en œuvrecreateEditor
méthode qui sera appelée automatiquement par la vue quand un éditeur est demandé pour une cellule:Noter que
connect
est ci-dessousappend
s parce que nous avons besoin pour évitercurrentIndexChanged
signaux lors de l'initialisation.4.
Mettre en œuvresetEditorData
méthode qui sera appelée par le point de vue où le modèle de données a été modifiée. Aussi, il sera appelé une fois quand un éditeur est initialisé.Encore une fois, nous voulons éviter que les signaux ne sont pas causés par l'utilisateur, de sorte que nous utilisons
blockSignals
.5.
Dans le logement nous avons simplement émettrecommitData
signal qui va provoquer l'affichage d'appeler lesetModelData
de notre délégué:6.
Mettre en œuvresetModelData
méthode:7.
Votre modèle a besoin de données de soutien en train de changer. Donc, nous devrions mettre en œuvresetData
méthode du modèle: