《给QTreeView表项添加CheckBox和图标》:系列教程之七

本文属于《QTreeView使用系列教程》之一,欢迎查看其它文章。

一、给树中item添加图标

接下来,我们分别给"省份"、"人口"添加不同图标。

首先,在TreeItem.cpp中添加getIcon函数,默认只有第一列"姓名"才允许有图标,再根据当前item类型,分别返回不同图标。

QVariant TreeItem::getIcon(int column)
{
    if (column != COLUMN_NAME)
        return QVariant();

    if(_type == PROVINCE)
    {
        return QIcon(":/res/province.png");
    }
    else if (_type == PERSON)
    {
        return QIcon(":/res/person.png");
    }
    return QVariant();
}

然后,我们在TreeModel.cpp中data()下,添加DecorationRole角色处理,这个就是代表需要返回图标的role。我们调用前面写好的函数返回图标。

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

    TreeItem *item = itemFromIndex(index);
    if (role == Qt::DisplayRole)
    {
        return item->data(index.column());
    }
    else if (role == Qt::DecorationRole) {
        return item->getIcon(index.column());
    }
    return QVariant();
}

效果:
在这里插入图片描述

二、给树中item添加CheckBox

接下来,我们为表项添加复选框。

首先,在TreeItem.cpp中添加3个函数,分别用于提供勾选状态给model,以及界面勾选状态改变后,保存新勾选状态值。checkable()用于判断当前item是否允许勾选。

bool TreeItem::isChecked() const { return _checked; }
void TreeItem::setChecked(bool check) { _checked = check; }
bool TreeItem::checkable(int column) const
{
    if (column != COLUMN_NAME) // 除第一列外,其他列不允许勾选
    {
        return false;
    }
    if(_type == PERSON) // 第一列中只允许"人口"勾选
    {
        return true;
    }
    return false;
}

然后,我们在TreeModel.cpp中data()下,添加CheckStateRole角色处理,这个就是代表需要返回勾选状态。我们调用前面写好的函数返回勾选状态。

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

    TreeItem *item = itemFromIndex(index);
    if (role == Qt::DisplayRole)
    {
        return item->data(index.column());
    }
    else if (role == Qt::DecorationRole) {
        return item->getIcon(index.column());
    }
    else if (role == Qt::CheckStateRole)
    {
        if (item->checkable(index.column()))
        {
            return item->isChecked() ? Qt::Checked : Qt::Unchecked;
        }
        return QVariant();
    }
    return QVariant();
}

此时,我们发现CheckBox已经可以显示出来了,但是不能勾选

我们还需要在TreeModel.cpp中添加2个基类重写函数:

在flags函数中根据item的checkable()判断当前item是否允许勾选,然后将结果flags返回。若没有重写这个flags函数,在界面上就无法勾选CheckBox。

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

    Qt::ItemFlags flags = QAbstractItemModel::flags(index);
    TreeItem *item = itemFromIndex(index);
    if (item->checkable(index.column()))
    {
        flags |= Qt::ItemIsUserCheckable;
    }
    return flags;
}

重写flags()后,相当于有操作CheckBox权限了,但是check状态也是需要保存的,所以状态改变后,需要我们保存下来,下次界面刷新才能显示check上。
重写setData函数,同样根据checkable()判断当前item是否允许勾选,若允许,则将check状态保存到item中,并发送dataChanged信号,返回true。

bool TreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid())
        return false;

    if (role == Qt::CheckStateRole)
    {
        TreeItem *item = itemFromIndex(index);
        if (!item->checkable(index.column()))
        {
            return false;
        }

        item->setChecked(value.toInt() == Qt::Checked);
        emit dataChanged(index, index);
        return true;
    }
    return false;
}

到此,我们的CheckBox就添加好了,并且也能够勾选了。

三、CheckBox的勾选改变处理

对model添加信号槽处理,捕获数据改变信号

TreeModel* model = new TreeModel(headers, treeView);
connect(model, &QAbstractItemModel::dataChanged,
    this, &MainWindow::onTreeDataChanged);
void MainWindow::onTreeDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
    TreeItem *item = static_cast<TreeItem*>(topLeft.internalPointer());
    if (item->checkable(topLeft.column()))
    {
        QString name = item->data(COLUMN_NAME).toString();
        if (item->isChecked())
        {
            qDebug() << "checked:" << name;
        }
        else
        {
            qDebug() << "unchecked:" << name;
        }
    }
}

效果:
在这里插入图片描述



若对你有帮助,欢迎点赞、收藏、评论,你的支持就是我的最大动力!!!

同时,阿超为大家准备了丰富的学习资料,欢迎关注公众号“超哥学编程”,即可领取。

本文涉及工程代码,公众号回复:34AddCheckIcon,即可下载。

在这里插入图片描述

  • 7
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
可以通过样式表为 QTreeView 的 branch 元素添加虚线来实现节点间的虚线效果。以下是一个示例: ```css QTreeView::branch:has-siblings:!adjoins-item { border-image: url(:/images/treeview-vline.png) 0; } QTreeView::branch:has-siblings:adjoins-item { border-image: url(:/images/treeview-branch-more.png) 0; } QTreeView::branch:!has-children:!has-siblings:adjoins-item { border-image: url(:/images/treeview-branch-end.png) 0; } QTreeView::branch:has-children:!has-siblings:closed, QTreeView::branch:closed:has-children:has-siblings { border-image: none; image: url(:/images/treeview-expand.png); } QTreeView::branch:open:has-children:!has-siblings, QTreeView::branch:open:has-children:has-siblings { border-image: none; image: url(:/images/treeview-collapse.png); } ``` 在上面的样式表中,我们使用了 `border-image` 属性来设置虚线图片作为节点间的分隔符,同时还使用了 `image` 属性来设置展开和折叠图标。其中,`:has-children` 伪状态表示该节点有子节点,`:has-siblings` 表示该节点有兄弟节点,`:adjoins-item` 表示该节点与其他节点相邻,`:closed` 表示该节点处于折叠状态,`:open` 表示该节点处于展开状态。 需要注意的是,为了保证样式表的正确应用,需要将 QTreeView 的 `setStyleSheet()` 方法中的 `QTreeView` 替换为 `QTreeView::branch`,即: ```python tree_view.setStyleSheet(""" QTreeView::branch:has-siblings:!adjoins-item { border-image: url(:/images/treeview-vline.png) 0; } ... """) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百里杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值