首页 > 解决方案 > Qt C++ QabstractTableModel 最初将复选框列设置为未选中

问题描述

我在从 QAbstractTableModel 继承的类上正确实现一列复选框时遇到问题。表格中的每一行都有一个复选框,当有新项目进入时,它最初会被选中,我需要取消选中它。

我曾尝试在 setData 中最初返回 Qt::unchecked,但是当我这样做时,我无法选中/取消选中该框。每个项目都有一个检查的内部属性,通过 is_Checked(item #)、set_Checked(item #) 访问。下面是来自 .cpp 文件的代码,使用 Qt 4.11

QVariant ClassItemModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
    {
        return QVariant();
    }

    int r = index.row();
    if (r >= m_data.size() || r < 0)
        return QVariant();

    int c = index.column();

    if (role == Qt::CheckStateRole)
    {
        if (c == 0)
        {
                //line below doesn't work since m_data[r].checked is set to false
                //initially, so when it returns Qt::Unchecked, it can't be toggled
                //
                //return m_data[r].is_Checked ? Qt::Checked : Qt::Unchecked

                //this works, but each new item in the table is initially checked since display is 
                //always true
                if (m_data[r].display)
                {
                    return Qt::Checked;
                }
                else
                {
                    return Qt::Unchecked;
                }
        }
    }

bool ClassItemmodel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid())
    {
        return false;
    }
    emit layoutAboutToBeChanged();
    int r = index.row();
    int c = index.column();

    if (role == Qt::CheckStateRole)
    {
        if (c == 0)
        {
            bool b = value.toBool();
            m_data[r].display = b;
            if(static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked)
            {
                set_Checked(r,false);
            }
            else
            {
                set_Checked(r,true);
            }
            if (!b)
            {
                emit layoutChanged();
            }
        }
    }
    return QAbstractItemModel::setData(index, value, role);
}

Qt::ItemFlags ClassItemModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return 0;

    int c = index.column();

    if (c == 0)
    {
        return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled;
    }
    ....
 }

标签: c++qtcheckboxqabstracttablemodel

解决方案


You are implementing setData() wrongly.

In data(), you can go back to using return m_data[r].is_Checked ? Qt::Checked : Qt::Unchecked;.

In setData(),

if (role == Qt::CheckStateRole)
{
    if (c == 0)
    {
        bool b = value.toBool();
        m_data[r].is_Checked = b;
        set_Checked(r, value == Qt::Checked);
        emit dataChanged(index, index, {role});
        if (!b)
            emit layoutChanged();
        return true;
    }
}
return QAbstractItemModel::setData(index, value, role);

Notice that dataChanged() has to be emited in the subclass and setData() returns true when the data is successfully set. The base class implementation always returns false.

Check QAbstractItemModel::setData()


推荐阅读