簡體   English   中英

自定義QStyledItemDelegate-將編輯應用於模型

[英]Custom QStyledItemDelegate - Applying Edits to Model

在我的項目中,我將QStyledItemDelegate子類化,並從createEditor函數返回了自定義編輯器。

QWidget* TagEditDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    TagEditWidget* tagEditWidget = new TagEditWidget(parent, index.data(Qt::UserRole+4).toInt(), index.data(Qt::UserRole+2).toByteArray(), index.data(Qt::UserRole+3).toByteArray(), index.parent().data(Qt::UserRole+4).toInt() == 9, parent->width());
    return tagEditWidget; //tagEditWidget is my custom QWidget
}

編輯完成后,我想將新數據寫回到模型中。 所以我覆蓋了setModelData

void TagEditDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const
{
    TagEditWidget * tagEditWidget = qobject_cast<TagEditWidget*>(editor);
    if (!tagEditWidget)
    {
        QStyledItemDelegate::setModelData(editor, model, index);
        return;
    }

    //Edit model here?
}

這行得通,但是問題是無論關閉編輯器如何,都會調用setModelData 我只想在使用EndEditHintQAbstractItemDelegate::SubmitModelCache關閉編輯器的情況下寫入新數據。 所以我將closeEditor信號連接到我創建的名為editFinished的插槽。

connect(this, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)), this, SLOT(editFinished(QWidget*,QAbstractItemDelegate::EndEditHint)));

現在,我可以看到如何通過EndEditHint關閉編輯器,以及是否應該將數據寫回到模型中。 closeEditor信號之前,Buuuuut, setModelData得到了調用。 closeEditor信號最后被調用時,如何將數據寫回到模型中? 我在這里想念什么嗎?

基本答案:

您的概念似乎很好,直到最后。 我將重點介紹TagEditDelegate::setModelData方法。

如果您實際上不想更新模型中的數據,只需檢查它是否沒有更改。 意思是當oldData == newData return; 並跳過模型更新。

補充筆記:

通過查看您的編輯器創建,我得到的印象是它不包含呈現給用戶的單個值。 為了使傳遞參數更友好並且更輕松地比較編輯器數據,請考慮為其創建單獨的class/struct 因此,您可以致電:

new TagEditWidget(parent, editorData, parent->width())

其中EditorData是您的類/結構,可以通過單獨的函數獲取:

EditorData editorData = readEditorData(index);

該函數可以在setModelData方法中重用以檢查條件:

if (tagEditWidget->getEditorData() == readEditorData(index)) return;

還要避免使用像Qt::UserRole+2這樣的幻數。 創建您自己的枚舉以指定所需的角色。 例如:

enum class MyRole
{
    Data1 = Qt::UserRole,
    Data2,
    Data3,
};

根據評論中的討論進行編輯

如果要發現用戶實際上是否沒有一種方式取消版本,則可以在編輯器或委托中覆蓋eventFilter 創建編輯器時,請在構造函數中調用installEventFilter 您的eventFilter實現可能如下所示:

bool eventFilter(QObject *object, QEvent *event) override
{
    if (event->type() == QEvent::KeyPress)
    {
        const auto key = static_cast<QKeyEvent *>(event)->key();
        if (key == Qt::Key_Enter || key == Qt::Key_Return || key == Qt::Key_Tab)
            submitted = true;
    }
    else if (event->type() == QEvent::FocusAboutToChange &&
             static_cast<QFocusEvent*>(event)->reason() == Qt::MouseFocusReason)
    {
        submitted = true;
    }
    // extetend the conditions (add else if) to include
    // events which you might want to treat as submitted

    return QLineEdit::eventFilter(object, event);
}

submitted是在構造函數中初始化為falsebool編輯器成員。 然后可以創建一個getter方法isSubmitted() ,並准備檢查setModelData方法中的狀態。

if (tagEditWidget->isSubmitted())
{
    // process data or update model here
}

我只是以自己的方式回答了自己的問題。 我認為,杜斯特的解決方案“更正確”。

我在名為shouldCommit的委托類中設置了布爾值,並將其設置為false。

然后在setModelData ,檢查是否應將數據寫入模型。

void TagEditDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const
{
    TagEditWidget * tagEditWidget = qobject_cast<TagEditWidget*>(editor);
    if (!tagEditWidget)
    {
        QStyledItemDelegate::setModelData(editor, model, index);
        return;
    }

    if(shouldCommit)
    {
        //write data here
    }
}

然后,在發出closeEditor信號時,我檢查了提示並將臨時設置shouldCommit設置為true, commitData再次調用commitData 現在, shouldCommit為true,數據被寫入。

void TagEditDelegate::editFinished(QWidget * editor, QAbstractItemDelegate::EndEditHint hint)
{
    if(hint == QAbstractItemDelegate::SubmitModelCache)
    {
        TagEditWidget * tagEditWidget = qobject_cast<TagEditWidget*>(editor);
        if(tagEditWidget)
        {
            shouldCommit = true;
            commitData(editor);
            shouldCommit = false;
        }
    }
}

盡管這對我的用例非常有效,但可能並非對所有人都適用,而且Dusteh的注釋部分可能對某些人更有用。 他的方法是重寫eventFilter並在何時調用commitData時編寫自己的實現。 對於想要更多控制的人來說,這可能是一個更合適的解決方案。

但是對於任何想要使用默認eventFilter實現並只看EndEditHint ,這就是我的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM