在 QStyledItemDelegate 中显示 QComboBox 文本而不是索引值

Posted

技术标签:

【中文标题】在 QStyledItemDelegate 中显示 QComboBox 文本而不是索引值【英文标题】:Displaying QComboBox text rather than index value in QStyledItemDelegate 【发布时间】:2010-08-25 17:00:02 【问题描述】:

所以我有一个模型,其中一列包含一个国家/地区。但是,因为我想显示一个组合框来从选项列表中选择国家,所以我不直接将国家名称存储在模型中。相反,我将索引值存储到允许的国家列表中。这允许我按照 Qt 文档中的建议在我的表单视图中使用QComboBox。问题是我也有一个表格视图,表格视图显示索引整数,而不是国家名称。我已经设置了QStyledItemDelegate 并实现了createEditor,所以如果你点击世界单元格,它会弹出ComboBox,但是当你不编辑国家时,你会看到索引值。

我正在寻求解决方案。我已经实现了一种绘制方法来完成这项工作,但它显示的是偏移到它的正确位置的值,我不知道如何让它正确显示。我认为render方法中的option.rect.topLeft()是错误的,但是我无法弄清楚如何正确设置绘图。

def paint(self, painter, option, index):
    if index.column() == COUNTRY:
        painter.save()
        countryRef, ok = inex.data().toInt()
        countryStr = country_list[countryRef]
        widget = QLineEdit()
        widget.setGeometry(option.rect)
        widget.setText(countryStr)
        widget.render(painter, option.rect.topLeft())
        painter.store()
    else:
        QStylyedItemDelegate.paint(self, painter, option, index)

【问题讨论】:

【参考方案1】:

模型对于不同的数据有不同的item data roles。有Qt::DisplayRoleQt::EditRoleQt::UserRole 等等。在这种情况下,您希望显示与实际数据不同的内容,因此添加一个新角色,例如用于您的索引的 Qt::UserRole+1

那么您希望您的委托在setModelData 中设置适当的数据:

def setModelData(self, editor, model, index):
    cbIndex = editor.currentIndex()
    model.setData(index, cbIndex, Qt.UserRole+1)
    # we want a nice displayable though
    model.setData(index, countryIndexToDisplayable(cbIndex), Qt.DisplayRole)

当然,您将以类似的方式检索要在编辑器中设置的数据:

def setEditorData(self, widget, index):
    widget.setCurrentIndex(index.data(Qt.UserRole+1))

根据您的模型和视图,您可能可以使用Qt::EditRole,这几乎就是为此目的而设计的。如果您随后使用本机类型作为显示角色,则不需要进行任何自定义绘画,但如果您愿意,也可以这样做。

【讨论】:

+1 非常出色,谢谢。我不知道您可以创建用户定义的角色。我的感觉是,如果您使用一个角色更新数据,模型应该处理更新该数据的所有其他角色,但这在示例中会更难显示。 次要问题,在委托的 setModelData 方法中,我必须将 cbIndex 转换为 QVariant,如下所示:model.setData(index, QVariant(cbIndex), Qt.UserRole+1)。这是因为我有一个使用 QDataWidgetMapper 访问数据的表单,它总是将 QVariants 发送到模型,我需要保持一致。模型可能应该总是返回数据并具有 Qt 原生数据类型的数据集,而不是 Python 类型? @Simon - 我的偏好是拥有一个丰富的模型,一个代表您正在使用的领域的词汇表的模型。所以我希望有一个名为setCountry 的方法,它带有一个用于将索引转换为国家/地区的助手。我喜欢制作一个丰富的模型,它不是QAbstractItemModel,而是我可以轻松地在 GUI 模型中委托给它的模型。如果我不这样做,我只需在 QAbstractItemModel 上创建提供更丰富 API 的访问器。 RE: QVariant(cbIndex),我已经有一段时间没有做任何 PyQt 并且我认为它会自动转换,就像在 C++ 中一样。 我明白你的意思,如果你用自己的访问器扩展模型,那么让它们尽可能方便是有意义的。不确定自动转换,PyQt 通常在这方面很棒,所以不知道那里发生了什么。也许是我的错。

以上是关于在 QStyledItemDelegate 中显示 QComboBox 文本而不是索引值的主要内容,如果未能解决你的问题,请参考以下文章

QStyledItemDelegate 绘制自定义小部件失败

QStyledItemDelegate - updateEditorGeometry 如何工作?

QStyledItemDelegate中如何根据qStylesheet进行绘制

在带有 QSqlQueryModel 的 QListView 上使用 QStyledItemDelegate

QListView 与 CustomWIdget 使用 QStyledItemDelegate

Qt入门教程数据模型篇QStyledItemDelegate样式代理类