Qt - 要求新模型行非空

Qt - requiring new model rows to be non-empty

我正在制作一个程序,用户可以在列表中添加多人(参与者)。单击 "Add" 按钮时,将添加一个新行并为名称字段调用 "edit"。到目前为止一切都很好,但有一件事我想实现,但我似乎无法弄清楚如何实现:当用户关闭编辑字段时(按 enter 或 escape,点击别处等),如果名称字段仍为空,我想删除该行。换句话说,必须填写一个名字。这是我目前所拥有的:

void MainWindow::addParticipant()
{
    QList<QStandardItem *> newRow;
    newRow << new QStandardItem()
           << new QStandardItem();
    participantModel->appendRow(newRow);
    participantView->edit(participantModel->index(participantModel->rowCount()-1, 0));
}

这里participantModel是一个QStandardItemModelparticipantView是一个QTreeView。我尝试使用信号和槽来检测一行何时为空并将其删除,但它没有用,语法对我来说难以捉摸。

理想情况下,我能够检测到名称字段何时不再被编辑,这样我就可以在需要时删除该行。

这是一个丑陋但有效的解决方案:从 QItemDelegate 子类化并检查 setModelData 成员函数内的输入数据。由于 setModelData 有一个 const 限定符,你不能修改它里面的模型,所以你需要一些技巧:在下面的例子中,模型在 closeEditor 信号的处理程序中被修改。

class MainWidget : public QWidget
{
Q_OBJECT
public:
    MainWidget ()
    {
        QStandardItemModel * model = new QStandardItemModel ();
        ItemDelegate * delegate = new ItemDelegate ();
        table->setItemDelegate (delegate);

        connect (delegate, & ItemDelegate::closeEditor, [=](){
            if (isEmpty) {
                model->removeRow (emptyRow);
                isEmpty  = false;
                emptyRow = -1;
            }
        });

        connect (delegate, & ItemDelegate::cellEdited, [=](const int row){
            isEmpty  = true;
            emptyRow = row;
        });
    }

    bool  isEmpty;
    int   emptyRow;
};

class ItemDelegate : public QItemDelegate
{
Q_OBJECT
signals:
    void cellEdited (int) const;
public:
    void setModelData (QWidget * widget, QAbstractItemModel * model, const QModelIndex & index) const override
    {
        if (0 == index.column () ) {
            if (QLineEdit * cellWidget = qobject_cast <QLineEdit *> (widget) ) {
                if (cellWidget->text ().isEmpty () ) {
                    emit cellEdited (index.row () );
                    return;
                }
            }
        }

        QItemDelegate::setModelData (widget, model, index);
    }
};

完整示例可在 GitLab 获得。

到目前为止发布的 comments/answers 敦促我更多地研究项目代表。非常尴尬,经过相对较少的谷歌搜索后,我找到了以下解决问题的方法:

void MainWindow::addParticipant()
{
    QStyledItemDelegate *participantDelegate = new QStyledItemDelegate;
    participantView->setItemDelegateForColumn(0, participantDelegate);    
    QList<QStandardItem *> newRow;
    newRow << new QStandardItem()
           << new QStandardItem();
    participantModel->appendRow(newRow);
    connect(participantDelegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)), this, SLOT(checkRow()));
    participantView->edit(participantModel->index(participantModel->rowCount()-1, 0));
}

显然 closeEditor 信号(仅对代表可用)正是我要找的。当编辑器关闭时,插槽checkRow()检查参与者的名称字段是否为空并决定是否删除该行。