我有一个带有可检查项目的 QListWidget,到目前为止它工作正常。现在我不仅想通过单击小复选框矩形来检查项目,而且还想通过单击项目本身来检查项目。
所以我实现了这个功能
void TagList::on_tagList_itemClicked(QListWidgetItem *item)
{
if( item==nullptr )
return;
clicked_ = true;
if( item->data(Qt::CheckStateRole) != Qt::Checked )
item->setData( Qt::CheckStateRole, Qt::Checked );
else
item->setData( Qt::CheckStateRole, Qt::Unchecked );
clicked_ = false;
}
Run Code Online (Sandbox Code Playgroud)
(clicked_ 是我接下来描述的脏黑客的类变量。)
它设置了项目单击时的检查状态,但是现在项目不再可以通过单击复选框矩形来检查,因为它被 ListWidget 和我的插槽切换了两次。不幸的是,ListWidget 仅使用单列模型,因此我无法区分对复选框的点击和对模型索引对项目的点击。
然后我也实现了
void TagList::onModelItemChanged(QModelIndex tl, QModelIndex br, QVector<int> roles)
{
if( (roles.empty() || roles.contains(Qt::CheckStateRole)) && !clicked_ ){
qDebug() << "changed with no click";
clicked_ = true;
if( tl.data(Qt::CheckStateRole)== Qt::Unchecked )
ui->tagList->model()->setData(tl,Qt::Checked,Qt::CheckStateRole);
else
ui->tagList->model()->setData(tl,Qt::Unchecked,Qt::CheckStateRole);
clicked_ = false;
}else{
qDebug() << "changed after click";
}
}
Run Code Online (Sandbox Code Playgroud)
并将其连接到模型的 dataChanged 信号。这工作正常,但列表也是可编辑的,因此每当我重命名列表中的对象时,检查状态就会更改,不幸的是列表小部件也忽略了 dataChanged 信号的角色向量。因此,roles.empty() 情况始终适用:( 并且重命名会触发 checkstate 更改...
有没有人对这种情况有一个简单的解决方案?我不想仅仅为了这个简单的案例创建自己的模型。
您只需要Qt::ItemIsUserCheckable在添加新项目时取消设置该标志:
void TagList::addNewTag(QString name)
{
QListWidgetItem *item= new QListWidgetItem(name, ui->tagList);
item->setFlags(item->flags() & (~Qt::ItemIsUserCheckable));
item->setCheckState(Qt::Unchecked);
ui->tagList->addItem(item);
}
Run Code Online (Sandbox Code Playgroud)
这样当用户单击复选框时,项目的选中状态不会改变。
on_tagList_itemClicked然后像您一样实现插槽:
void TagList::on_tagList_itemClicked(QListWidgetItem *item)
{
if(item == nullptr)
return;
if(item->data(Qt::CheckStateRole) != Qt::Checked)
item->setData(Qt::CheckStateRole, Qt::Checked);
else
item->setData(Qt::CheckStateRole, Qt::Unchecked);
}
Run Code Online (Sandbox Code Playgroud)
黑客但可行的解决方案是在模型的每个 datachanged 信号上启动 QTimer::singleshot() 60ms,并阻止 itemClicked 信号直到计时器完成。
如果您有更好的解决方案,请告诉我。