Sfondo: Non riesco a trovare un esempio funzionante completo di una casella combinata all'interno di QTableView
. Così ho scritto questo codice basato su molti altri esempi più elaborati là fuori. Il problema è, tuttavia, che in questo esempio è necessario fare doppio clic sulla combobox prima che venga abilitato, quindi è necessario fare nuovamente clic per rilasciarlo. Non è molto user-friendly. Se eseguo la non-model/view-thing usando QTableWidget
, la casella combinata scende al primo clic.PyQt - esempio di funzionamento più semplice di una casella combinata all'interno di QTableView
Domanda: Qualcuno può guardare questo e dirmi cosa deve essere fatto per farlo rispondere come QTableWidget
? Inoltre, se c'è qualcosa che sto facendo che non è necessario, si prega di indicare anche questo. Ad esempio, è assolutamente necessario fare riferimento allo stile dell'applicazione?
import sys
from PyQt4 import QtGui, QtCore
rows = "ABCD"
choices = ['apple', 'orange', 'banana']
class Delegate(QtGui.QItemDelegate):
def __init__(self, owner, items):
super(Delegate, self).__init__(owner)
self.items = items
def createEditor(self, parent, option, index):
self.editor = QtGui.QComboBox(parent)
self.editor.addItems(self.items)
return self.editor
def paint(self, painter, option, index):
value = index.data(QtCore.Qt.DisplayRole).toString()
style = QtGui.QApplication.style()
opt = QtGui.QStyleOptionComboBox()
opt.text = str(value)
opt.rect = option.rect
style.drawComplexControl(QtGui.QStyle.CC_ComboBox, opt, painter)
QtGui.QItemDelegate.paint(self, painter, option, index)
def setEditorData(self, editor, index):
value = index.data(QtCore.Qt.DisplayRole).toString()
num = self.items.index(value)
editor.setCurrentIndex(num)
def setModelData(self, editor, model, index):
value = editor.currentText()
model.setData(index, QtCore.Qt.DisplayRole, QtCore.QVariant(value))
def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect)
class Model(QtCore.QAbstractTableModel):
def __init__(self):
super(Model, self).__init__()
self.table = [[row, choices[0]] for row in rows]
def rowCount(self, index=QtCore.QModelIndex()):
return len(self.table)
def columnCount(self, index=QtCore.QModelIndex()):
return 2
def flags(self, index):
return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
def data(self, index, role):
if role == QtCore.Qt.DisplayRole:
return self.table[index.row()][index.column()]
def setData(self, index, role, value):
if role == QtCore.Qt.DisplayRole:
self.table[index.row()][index.column()] = value
class Main(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.model = Model()
self.table = QtGui.QTableView()
self.table.setModel(self.model)
self.table.setItemDelegateForColumn(1, Delegate(self, ["apple", "orange", "banana"]))
self.setCentralWidget(self.table)
self.setWindowTitle('Delegate Test')
self.show()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
main = Main()
app.exec_()
Si possono trovare la mia risposta a [questa domanda] (http://stackoverflow.com/questions/17615997/pyqt-how-to-set-qcombobox-in- a-table-view-using-qitemdelegate) utile. –
Grazie, ora vedo che l'override di 'paint' non è necessario, e ho bisogno di' openPersistentEditor'. Ma chiamare 'openPersistentEditor' sembra sconfiggere lo scopo del modello/vista se devo chiamarlo dall'esterno del modello. Inoltre, sembra inefficiente disegnare tutte quelle caselle combinate quando puoi operare solo una alla volta. C'è un modo per eliminare il requisito del doppio clic in modo che appaia sulla selezione delle celle? – user2120303
Non è necessario chiamarlo dal modello. Puoi utilizzare un altro oggetto (ad es. La tua vista o forma sottoclasse) per tracciare la modifica del modello e richiamare l'editor se necessario. Per la seconda domanda, collega il segnale 'selectionChanged' di' view-> selectionModel() 'allo slot. In questo slot aprire l'editor nella cella selezionata e chiudere gli editor precedenti se necessario. –