QT笔记- QTreeView设置三态setAutoTristate() 树形视图自动复选框——源码分享

本文介绍了如何在Qt中绕过QStandardItem::setAutoTristate()的限制,通过自定义派生类AutoTristateItem和AutoTristateTreeView来实现自动三态复选框功能。作者详细展示了如何编写代码,并给出了一个使用示例和关键信号槽的实现。
摘要由CSDN通过智能技术生成

说明

        Qt中函数QStandardItem::setAutoTristate()无实际功能,仅作为一个布尔标记。若要实现自动三态复选框功能,需要自行代码构建。

        本文通过编写两个派生类,完成了这个功能。类源码和一个示例如下:

源码

//[自动三态item](用于AutoTristateTreeView)
#include "QStandardItem"
class AutoTristateItem : public QStandardItem
{
    struct{
        int oldCheckState;
        bool oldShock;
    }info;
    void setAutoTristate(bool tristate);
public:
    AutoTristateItem() : QStandardItem()
    {info.oldCheckState = checkState(); info.oldShock = isAutoTristate();}
    AutoTristateItem(const QString &text) : QStandardItem(text)
    {info.oldCheckState = checkState(); info.oldShock = isAutoTristate();}
    int oldCheckState(){return info.oldCheckState;}
    void updateOldCheckState()
    {info.oldCheckState = checkState();}//setCheckState()后一般要调用一下该函数, 否则下一次可能不会触发后面的树

    //触发当前item之下的所有树的check box与当前item保持一致
    void shocking(){info.oldShock = isAutoTristate(); QStandardItem::setAutoTristate(!info.oldShock);}
    bool oldShock(){return info.oldShock;}
};

//[自动三态树形视图]
#include "QTreeView"
class AutoTristateTreeView : public QTreeView
{
    Q_OBJECT
public:
    enum AutoMode{
        AutoTristateMode,//必须同时设置setUserTristate(true)
        AutoTwoStateMode,//必须同时设置setUserTristate(false)
        None
    };
    explicit AutoTristateTreeView(QWidget *parent = 0) : QTreeView(parent){}
    virtual void setModel(QStandardItemModel *model);
    AutoMode autoMode(){return info.autoMode;}
    void setAutoMode(AutoMode mode){info.autoMode = mode;}
signals:
    void tristate_changed_(AutoTristateItem *item);//发送出check box发生变动的item
private slots:
    void _item_changed(QStandardItem *item);
private:
    struct{
        AutoMode autoMode = None;
    }info;
};

实现:

void AutoTristateTreeView::setModel(QStandardItemModel *model)
{
    QTreeView::setModel(model);
    connect(model, &QStandardItemModel::itemChanged, this, &AutoTristateTreeView::_item_changed);
}

void AutoTristateTreeView::_item_changed(QStandardItem *item)
{
    //    cout << "AutoTristateTreeView::_item_changed - " << endl;
    if(((AutoTristateItem *)item)->oldCheckState() != item->checkState() ||//区分是否是checked的改变
            ((AutoTristateItem *)item)->oldShock() != item->isAutoTristate()){
        if(((AutoTristateItem *)item)->oldCheckState() != item->checkState()){
            ((AutoTristateItem *)item)->updateOldCheckState();
            emit tristate_changed_((AutoTristateItem *)item);
            cout << "AutoTristateTreeView::_item_changed - Changed item:"
                 << qPrintable(item->text()) << endl;
        }
        for(int i = 0; i < item->rowCount(); ++i) {//只需控制其直接child即可
            switch (info.autoMode) {
            case AutoTristateMode:
                if(item->child(i)->isUserTristate()){
                    if(item->child(i)->checkState() == item->checkState())
                        ((AutoTristateItem *)(item->child(i)))->shocking();
                    else item->child(i)->setCheckState(item->checkState());
                }
                break;
            case AutoTwoStateMode:
                if(!item->child(i)->isUserTristate()){
                    if(item->child(i)->checkState() == item->checkState())
                        ((AutoTristateItem *)(item->child(i)))->shocking();
                    else item->child(i)->setCheckState(item->checkState());
                }
                break;
            default:
                break;
            }
        }
    }
}

示例:

        AutoTristateTreeView类中带有一个信号函数tristate_changed_(),用于将复选框发生变动的item发送出去。下面示例中使用了这个信号,用于将触发的item输出到窗口,但这里并没有贴出其槽函数的实现。

QStandardItemModel * model = new QStandardItemModel;
AutoTristateItem * item = new AutoTristateItem("test");
item->setCheckable(true);
item->setUserTristate(true);
AutoTristateItem * item2 = new AutoTristateItem("test_2");
item2->setCheckable(true);
item2->setUserTristate(true);
item->appendRow(item2);
AutoTristateItem * item3 = new AutoTristateItem("test_3");
item3->setCheckable(true);
item3->setUserTristate(true);
item->appendRow(item3);
AutoTristateItem * item4 = new AutoTristateItem("test_4");
item4->setCheckable(true);
item4->setUserTristate(true);
item3->appendRow(item4);
model->appendRow(item);

ui->treeView->setModel(model);
ui->treeView->setAutoMode(AutoTristateTreeView::AutoTristateMode);
connect(ui->treeView, &AutoTristateTreeView::tristate_changed_, this, &Widget::_tristate_changed);

调试:

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值