根据 Jason 提供的想法,我想出了这个解决方案。
为了通过单击启动编辑器,我将视图的 QAbstractItemView::clicked(const QModelIndex &index) 信号连接到同一视图的 QAbstractItemView::edit(const QModelIndex &index) 插槽。
如果你使用Qt4,你需要在你的委托中创建一个槽。将您的组合框作为参数传递给此插槽。在此插槽中,您调用QComboBox::showPopup。所以它看起来像这样:
void MyDelegate::popUpComboBox(QComboBox *cb)
{
cb->showPopup();
}
但首先我们需要注册QComboBox* 类型。您可以在委托的构造函数中调用它:
qRegisterMetaType<QComboBox*>("QComboBox*");
我们需要这个插槽的原因是因为我们不能在MyDelegate::createEditor 中直接显示弹出窗口,因为列表视图的位置和矩形是未知的。所以我们要做的是在MyDelegate::createEditor,我们用一个排队的连接来调用这个槽:
QComboBox *cb = new QComboBox(parent);
// populate your combobox...
QMetaObject::invokeMethod(const_cast<MyDelegate*>(this), "popUpComboBox", Qt::QueuedConnection, Q_ARG(QComboBox*, cb));
这将在激活编辑器时正确显示组合框的列表视图。
现在,如果您使用的是 Qt5,则不需要该插槽。您所要做的就是使用来自MyDelegate::createEditor 的排队连接呼叫QComboBox::showPopup。最简单的方法是使用QTimer:
QTimer::singleShot(0, cb, &QComboBox::showPopup);
对于一些额外信息,您可以通过以下方式绘制组合框,使其始终显示,而不仅仅是在显示编辑器时:
void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(index.column() == 1) // show combobox only in the second column
{
QStyleOptionComboBox box;
box.state = option.state;
box.rect = option.rect;
box.currentText = index.data(Qt::EditRole).toString();
QApplication::style()->drawComplexControl(QStyle::CC_ComboBox, &box, painter, 0);
QApplication::style()->drawControl(QStyle::CE_ComboBoxLabel, &box, painter, 0);
return;
}
QStyledItemDelegate::paint(painter, option, index);
}