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

2 投票
1 回答
1803 浏览
提问于 2025-04-16 03:17

我有一个模型,其中有一列是国家名。不过因为我想在表单中显示一个下拉框,让用户从选项中选择国家,所以我并没有直接把国家名存储在模型里。相反,我把一个索引值存储在一个允许的国家列表中。这样我就可以在我的表单视图中使用QComboBox,这也是Qt文档推荐的做法。问题是我还有一个表格视图,而这个表格视图显示的是索引整数,而不是国家名。我设置了一个QStyledItemDelegate,并实现了createEditor,所以当你点击单元格时,它会弹出ComboBox,但当你不在编辑国家时,你看到的还是索引值。

我已经部分解决了这个问题。我实现了一个绘制方法来处理这个问题,但它显示的值偏离了正确的位置,我还没搞清楚怎么才能让它正确显示。我觉得在渲染方法中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 个回答

4

模型有不同的数据角色来处理不同类型的数据。比如有一个叫Qt::DisplayRole的角色,用来显示数据,还有一个Qt::EditRole的角色,用来编辑数据,还有一个Qt::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,这个角色基本上就是为了这个目的而设计的。如果你在显示角色中使用原生类型,那么通常不需要进行任何自定义绘制,当然如果你愿意的话,也可以进行自定义。

撰写回答