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
是一个QStandardItemModel
,participantView
是一个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()
检查参与者的名称字段是否为空并决定是否删除该行。
我正在制作一个程序,用户可以在列表中添加多人(参与者)。单击 "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
是一个QStandardItemModel
,participantView
是一个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()
检查参与者的名称字段是否为空并决定是否删除该行。