我实现了以下委托,在QTableView中提供了一个组合框。用例是用对应的文本替换对用户通常没有意义的列(键)(例如数字id)。
下面的代码段有效(也用于保存正确的值),但它有三个问题:
注意:键可以是任何字符串(不一定是整数)。 一个典型的例子是国家(值“法国”对应于键“FR”)。
class ComboDelegate(QtGui.QItemDelegate):
"""
A delegate that places a QComboBox in every
cell of the column to which it is being applied
"""
def __init__(self, parent, value_data):
"Value_data is a list of tuples: (item, label)"
QtGui.QItemDelegate.__init__(self, parent)
self.value_data = value_data
@property
def items(self):
"The list of items for display"
return [item[0] for item in self.value_data]
@property
def labels(self):
"The list of labels for display"
return [item[1] for item in self.value_data]
def item(self, label):
"Get the item from a label"
try:
index = self.labels.index(label)
except ValueError:
pass
print("Value no: &%s" % index)
return self.items[index]
def createEditor(self, parent, option, index):
"Create the editor (called each time)"
combo = QtGui.QComboBox(parent)
for duplet in self.value_data:
# the duplet is label, item
item, label = duplet
combo.addItem(label)
combo.currentIndexChanged.connect(self.currentIndexChanged)
return combo
def setEditorData(self, editor, index):
editor.blockSignals(True)
editor.setCurrentIndex(index.row())
editor.blockSignals(False)
def setModelData(self, editor, model, index):
"This is the data stored into the field"
print("Current text: %s" % editor.currentText())
model.setData(index, self.item(editor.currentText()))
def currentIndexChanged(self):
self.commitData.emit(self.sender())
答案 0 :(得分:2)
添加{your table view}.openPersistentEditor({your QModelIndex})
这是我的解决方案:
import sys
from PySide import QtGui, QtCore
class ComboBoxDelegate(QtGui.QItemDelegate):
def __init__(self, parent=None):
super(ComboBoxDelegate, self).__init__(parent)
self.items = []
def setItems(self, items):
self.items = items
def createEditor(self, widget, option, index):
editor = QtGui.QComboBox(widget)
editor.addItems(self.items)
return editor
def setEditorData(self, editor, index):
value = index.model().data(index, QtCore.Qt.EditRole)
if value:
editor.setCurrentIndex(int(value))
def setModelData(self, editor, model, index):
model.setData(index, editor.currentIndex(), QtCore.Qt.EditRole)
def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect)
def paint(self, painter, option, index):
text = self.items[index.row()]
option.text = text
QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_ItemViewItem, option, painter)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
column = 0
model = QtGui.QStandardItemModel(4, 2)
tableview = QtGui.QTableView()
tableview.setModel(model)
delegate = ComboBoxDelegate()
delegate.setItems([str(x) for x in range(10)])
tableview.setItemDelegateForColumn(column, delegate)
for row in range(4):
for col in range(2):
index = model.index(row, col, QtCore.QModelIndex())
value = (row + 1)*(col + 1)
model.setData(index, value)
for i in range(model.rowCount()):
tableview.openPersistentEditor(model.index(i, column))
tableview.show()
sys.exit(app.exec_())
放置了字符串,因为我在上一个示例中使用的是str()
,我向您展示了另一个显示国家/地区的示例。
import sys
from PySide import QtGui, QtCore
class ComboBoxDelegate(QtGui.QItemDelegate):
def __init__(self, parent=None):
super(ComboBoxDelegate, self).__init__(parent)
self.items = []
def setItems(self, items):
self.items = items
def createEditor(self, widget, option, index):
editor = QtGui.QComboBox(widget)
editor.addItems(self.items)
return editor
def setEditorData(self, editor, index):
value = index.model().data(index, QtCore.Qt.EditRole)
if value:
editor.setCurrentIndex(int(value))
def setModelData(self, editor, model, index):
model.setData(index, editor.currentIndex(), QtCore.Qt.EditRole)
def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect)
def paint(self, painter, option, index):
text = self.items[index.row()]
option.text = text
QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_ItemViewItem, option, painter)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
column = 0
model = QtGui.QStandardItemModel(4, 2)
tableview = QtGui.QTableView()
tableview.setModel(model)
delegate = ComboBoxDelegate()
delegate.setItems([QtCore.QLocale.countryToString(QtCore.QLocale.Country(locale)) for locale in range(QtCore.QLocale.Afghanistan, QtCore.QLocale.Zulu+ 1 )])
tableview.setItemDelegateForColumn(column, delegate)
for row in range(4):
for col in range(2):
index = model.index(row, col, QtCore.QModelIndex())
value = (row + 1)*(col + 1)
model.setData(index, value)
for i in range(model.rowCount()):
tableview.openPersistentEditor(model.index(i, column))
tableview.show()
sys.exit(app.exec_())
答案 1 :(得分:1)
第一个问题最容易通过模型解决,即它可以在被要求DisplayRole
时提供特定值的文本,并且仍然通过EditRole
提供数值。
为了显示组合框,有两个选项
使用委托时,覆盖paint()
方法以绘制组合框,例如通过委托当前的小部件样式,就像QComboBox
本身一样
而不是委托,设置索引小部件。见QAbstractItemView::setIndexWidget()