0

我有一个从 QItemDelegate 子类化的自定义委托,它在第一列中提供一个 QComboBox,在所有其他列中提供一个 QLineEdit。

SensorDisplayDelegate::SensorDisplayDelegate(QObject *parent) :
    QItemDelegate(parent)
{}

QWidget *SensorDisplayDelegate::createEditor(QWidget *parent,
                                             const QStyleOptionViewItem &option,
                                             const QModelIndex &index) const
{
    int col = index.column();
    if(col == 0)
    {
        QComboBox *comboBox = new QComboBox(parent);
        connect(comboBox, SIGNAL(activated(int)), this, SLOT(setData(int)));
        comboBox->setEditable(false);
        //comboBox->setMaximumSize(editorSize);
        comboBox->setInsertPolicy(QComboBox::NoInsert);
        currentComboBox = comboBox;
        return comboBox;
    }
    else       
    {
        QLineEdit *lineEdit = new QLineEdit(parent);
        return lineEdit;
    }

    return NULL;
}

void SensorDisplayDelegate::setEditorData(QWidget *editor,
                                          const QModelIndex &index) const
{
    int col = index.column();
    if(col == 0)
    {
        QComboBox *comboBox = static_cast<QComboBox*>(editor);
        QStringList comboItems = index.data(Qt::EditRole).toStringList();

        comboBox->addItem("Add New Sensor");
        comboBox->addItems(comboItems);

        QCompleter *completer = new QCompleter(comboItems);
        completer->setCaseSensitivity(Qt::CaseInsensitive);
        comboBox->setCompleter(completer);
        comboBox->showPopup();
    }
    else
    {
        QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
        lineEdit->setText(index.data(Qt::EditRole).toString());
        lineEdit->show();
    }
}

void SensorDisplayDelegate::setModelData(QWidget *editor,
                                         QAbstractItemModel *model,
                                         const QModelIndex &index) const
{
    int col = index.column();
    if(col == 0)
    {
        QComboBox *comboBox = static_cast<QComboBox*>(editor);
        if(comboBox->currentIndex() == 0)
            emit addNewSensor();
        else
            emit populateSensorView(comboBox->currentText());
    }
    else
    {
        QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
        model->setData(index, QVariant(lineEdit->text()));
    }

}

void SensorDisplayDelegate::updateEditorGeometry(QWidget *editor,
    const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{
    editor->setGeometry(option.rect);
}

QSize SensorDisplayDelegate::sizeHint(const QStyleOptionViewItem &option,
                                      const QModelIndex &index) const
{
    return editorSize;
}


void SensorDisplayDelegate::setData(int option)
{
    emit commitData(currentComboBox);
    emit closeEditor(currentComboBox);
}

editTrigger 已设置为 selectClicked。我希望组合框覆盖 QTableView 中的整个单元格。但是,现在它只是在左手角显示为光点。我尝试通过在 QTableView 上侦听 mousePressed 的事件过滤器传递单元格大小来设置最小大小。但是,委托中的相应槽永远不会被调用。这是代码:

MultiEventFilter.cpp:

bool MultiEventFilter::eventFilter(QObject *obj, QEvent *event)
{
    if(event->type() == QEvent::MouseButtonPress)
    {
        if(obj->objectName() == "sensorlocationTableView")
        {
            QTableView *sensorView = static_cast<QTableView*>(obj);
            QModelIndexList idxs = sensorView->selectionModel()->selectedIndexes();
            if(!idxs.empty())
            {
                QModelIndex idx = idxs.at(0);
                emit passCellSize(QSize(sensorView->columnWidth(idx.column()),
                                        sensorView->rowHeight(idx.row())));
            }
        }
    }

    return false;
}

安装在qApp上。

主窗口.cpp:

eFilter = new MultiEventFilter();
    connect(eFilter, SIGNAL(passCellSize(QSize)),
            sensor_display_delegate, SLOT(setEditorSize(QSize)));

SensorDisplayDelegate.cpp 插槽:

void SensorDisplayDelegate::setEditorSize(const QSize &size)
{
    editorSize = size;
}

其中 QSize editorSize 是私有成员。如何正确设置编辑器的大小?我需要一些通用的东西,也可以应用于 QLineEdit 编辑器。另外,关闭编辑器时是否有必要显式发出 commitData() ?我没有在任何涉及 QComboBox 的示例代码中看到这样做。

4

1 回答 1

0

我怀疑您eventFilter在设置选择索引之前拦截了点击事件。那么,您实际上总是在点击一个空的idxsIndexList 吗?

尝试用类似的东西替换那个循环:

bool MultiEventFilter::eventFilter(QObject *obj, QEvent *event)
{
    if(event->type() == QEvent::MouseButtonPress)
    {
        if(obj->objectName() == "sensorlocationTableView")
        {
            emit locationTableViewClicked();
        }
    }

    return false;
}

....

connect(eFilter, SIGNAL(locationTableViewClicked()),
        sensor_display_delegate, SLOT(setEditorSize()));
...

void SensorDisplayDelegate::setEditorSize()
{
    QModelIndexList idxs = sensorView->selectionModel()->selectedIndexes();
    if(!idxs.empty())
    {
        QModelIndex idx = idxs.at(0);
        editorSize = QSize(sensorView->columnWidth(idx.column()),
                           sensorView->rowHeight(idx.row()));
    }
}
于 2017-01-02T15:10:15.007 回答