QListWidget,项目点击时可检查项目

时间:2015-03-09 14:34:37

标签: c++ qt

我有一个带有可检查项目的QListWidget,到目前为止工作正常。现在我想检查项目,不仅要点击小复选框rect,而只需点击项目本身。

所以我实现了函数

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;
}

(clicked_是我下次描述的脏黑客的类变量。)

在项目点击中设置检查状态,但是现在,通过单击复选框rect,不再可以检查项目,因为它被ListWidget和我的插槽切换两次。 不幸的是,ListWidget只使用单个列模型,所以我无法区分点击到Checkbox和点击模型索引的项目。

然后我也实施了

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";
}
}

并将其连接到模型的dataChanged信号。这工作正常但是列表也是可编辑的,因此每当我重命名列表中的对象时,检查状态就会发生变化,不幸的是List Widget也会忽略dataChanged信号的角色向量。所以roles.empty()情况总是适用:(并且重命名会触发checkstate更改......

有没有人为这个案例提供简单的解决方案?我不想仅仅为这个简单的案例创建我自己的模型。

2 个答案:

答案 0 :(得分:1)

添加新项目时,您只需要取消设置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);
}

当用户点击复选框时,项目的检查状态不会改变。

然后像您一样实施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);
}

答案 1 :(得分:0)

hacky但工作解决方案是在模型的每个datachanged信号上启动QTimer :: singleshot()60ms,并阻止itemClicked信号直到计时器结束。

如果您有更好的解决方案,请告诉我。