Qt 简单写一个TreeView,控制图层

背景:

近期要用Qt写一个 加载渲染激光点云的小工具软件, 对于这种软件来说,首先要有一个图层树来方便控制.因而做了一个小demo来记录一下;

效果展示:

要完成的功能: 增,删,改,查,收起,以及展开的操作效果.以及对自己定义

 实现过程:

1.先定义自己的数据结构:

#include <iostream>
#include <list>
/// <summary>
/// Tree 基础图元
/// </summary>
class IXPloteTreeItem
{
public:

    IXPloteTreeItem();
    ~IXPloteTreeItem();
    static long XPloteNumsID;//全局的ID
    void SetData(const std::string& name);
    int GUID;
    std::string gName{ "" };
    std::shared_ptr<std::list<IXPloteTreeItem>> gChilds{ nullptr };
    std::string toString() const;
};

2.定义TreeStandItem,来包裹自己的结构

 XPloteStandardItem.h头文件.

#include <qstandarditemmodel.h>
#include "IXPloteTreeItem.h"

/// <summary>
/// 创建自己的QstandItem 子项目.
/// </summary>
class XPloteStandardItem :public QStandardItem
{
public:

	using QStandardItem::QStandardItem;
	XPloteStandardItem() :QStandardItem() {
	
		InitData();
	
	}
	XPloteStandardItem(const QString& str) :QStandardItem(str) 
	{
		InitData();
		gTreeData->gName = str.toStdString().c_str();
	}
	~XPloteStandardItem();
	std::shared_ptr<IXPloteTreeItem> gTreeData{ nullptr };

private:

	void InitData();

};


 XPloteStandardItem.cpp文件

#include "XPloteStandardItem.h"
#include <memory>
XPloteStandardItem::~XPloteStandardItem()
{

}

void XPloteStandardItem::InitData()
{
	if(gTreeData==nullptr) gTreeData = std::make_shared<IXPloteTreeItem>();
	this->setCheckable(true);
	this->setCheckState(Qt::Checked);
	this->setEditable(false);
}

3.UI上面我就不写了,随便拖一个TreeView控件上去,主要是下面的关键代码以及实现过程:

 QtTree.h 类头文件

/// <summary>
/// 主窗体函数.
/// </summary>
class QtTree : public QMainWindow
{
    Q_OBJECT

public:

    QtTree(QWidget *parent = nullptr);
    
    ~QtTree();

    void InitSource();

public slots:

    void on_treeView_customContextMenuRequested(const QPoint &pos);

private:

    Ui::QtTreeClass ui;
    QMenu* menu;
    QStandardItemModel* model;
    QStandardItem* rootItem1;
    QStandardItem* rootItem2;
};

 QtTree.cpp实现部分:

#include "QtTree.h"
#include <QMessageBox>

QtTree::QtTree(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    InitSource();
}

QtTree::~QtTree()
{


}

void PrintLog(const std::string& str)
{
    QMessageBox::information(nullptr,"",str.c_str());
}
void PrintLog(QString str)
{
    QMessageBox::information(nullptr, "", str);
}

void QtTree::InitSource()
{

    ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu);
    //添加右键菜单...
    QString qss = "QMenu{color:#E8E8E8;background:#4D4D4D;margin:2px;}\
                QMenu::item{padding:3px 20px 3px 20px;}\
                QMenu::indicator{width:13px;height:13px;}\
                QMenu::item:selected{color:#E8E8E8;border:0px solid #575757;background:#1E90FF;}\
                QMenu::separator{height:1px;background:#757575;}";      //设置样式表
    menu = new QMenu(ui.treeView);
    menu->setStyleSheet(qss);                                         //给菜单设置样式
    QAction* a1 = new QAction(QStringLiteral("增加"));
    menu->addAction(a1);   
    connect(a1, &QAction::triggered, this, [&]() {
        
        QModelIndex curIndex = ui.treeView->currentIndex();
        if (curIndex.isValid())
        {
#if 0
            auto parentIndex = curIndex.parent();
            if (parentIndex.isValid())
            {
                auto parentItem = model->itemFromIndex(parentIndex);
                if (parentItem != nullptr)
                {
                    parentItem->appendRow(new QStandardItem(QStringLiteral("城市_%1").arg(model->rowCount())));
                }
            }
            else
            {
                //model
                model->appendRow(new QStandardItem(QStringLiteral("城市_%1").arg(model->rowCount())));
            }

#else

            auto curItem = model->itemFromIndex(curIndex);
            if (curItem != nullptr)
            {
                auto item = new XPloteStandardItem(QStringLiteral("城市_%1").arg(model->rowCount()));
                item->setCheckable(true);
                item->setCheckState(Qt::Checked);
                curItem->appendRow(item);
            }


#endif // 0


        }
        
        
        });   
   
  
    QAction* a2 = new QAction(QStringLiteral("查看"));
    menu->addAction(a2);
    connect(a2, &QAction::triggered, this, [&]() {

        QModelIndex curIndex = ui.treeView->currentIndex();
        if (curIndex.isValid())
        {
        
            auto curItem = static_cast<XPloteStandardItem*>((model->itemFromIndex(curIndex)));
            if (curItem != nullptr)
            {
                QString info;
                info.append(curItem->text());//获取当前文本.
                info.append(QStringLiteral("\r\n状态: %1\r\n").arg(curItem->checkState()));
                info.append(QStringLiteral("自己的数据(IXPloteTreeItem): %1").arg(curItem->gTreeData->toString().c_str()));
                PrintLog(info);
            }
        
        }
      
        });

    QAction* a5 = new QAction(QStringLiteral("展开"));
    menu->addAction(a5);
    connect(a5, &QAction::triggered, this, [&]() {

        QModelIndex curIndex = ui.treeView->currentIndex();
        if (curIndex.isValid())
        {
            ui.treeView->expand(curIndex);
        }

        });

    QAction* a6 = new QAction(QStringLiteral("收起"));
    menu->addAction(a6);
    connect(a6, &QAction::triggered, this, [&]() {

        QModelIndex curIndex = ui.treeView->currentIndex();
        if (curIndex.isValid())
        {
            ui.treeView->collapse(curIndex);
        }

        });

    QAction* a3 = new QAction(QStringLiteral("修改"));
    menu->addAction(a3);
    connect(a3, &QAction::triggered, this, [&]() {

        QModelIndex curIndex = ui.treeView->currentIndex();
        if (curIndex.isValid())
        {

            auto curItem = static_cast<XPloteStandardItem*>((model->itemFromIndex(curIndex)));
            if (curItem != nullptr)
            {
                QString str = QStringLiteral("天朝");
                curItem->gTreeData->gName = str.toStdString();
                curItem->setText(str);
                PrintLog(QStringLiteral("修改完成"));
            }

        }

        });

    QAction* a4 = new QAction(QStringLiteral("删除"));
    menu->addAction(a4);
    connect(a4, &QAction::triggered, this, [&]() {

        QModelIndex curIndex = ui.treeView->currentIndex();
        if (curIndex.isValid())
        {
            auto parentIndex = curIndex.parent();
            if (parentIndex.isValid())
            {
                auto parentItem = model->itemFromIndex(parentIndex);
                parentItem->removeRow(curIndex.row());
            }
            else
            {
                model->removeRow(curIndex.row());
            }
           
        }

        });
    //给菜单添加项


    //添加一些Tree数据.
    {
        model = new QStandardItemModel(ui.treeView); //指定父对象,便于内存管理
        model->setHorizontalHeaderLabels(QStringList() << QStringLiteral("名称") << QStringLiteral("说明"));
        ui.treeView->setModel(model);//设置数据Model,关键.

        rootItem1 = new XPloteStandardItem(QStringLiteral("北京"));
        model->appendRow(rootItem1);

        XPloteStandardItem* childItem1_1 = new XPloteStandardItem(QStringLiteral("故宫"));
        rootItem1->appendRow(childItem1_1);
        XPloteStandardItem* childItem1_2 = new XPloteStandardItem(QStringLiteral("子午庙"));
        rootItem1->appendRow(childItem1_2);
        rootItem1->appendRow(new XPloteStandardItem(QStringLiteral("日月潭")));
        rootItem1->appendRow(new XPloteStandardItem(QStringLiteral("中南海")));

        rootItem2 = new XPloteStandardItem(QStringLiteral("湖北"));
        model->appendRow(rootItem2);
        //model->setItem(model->indexFromItem(rootItem2).row(), 1, new XPloteStandardItem(QStringLiteral("黄鹤楼")));//设置第二列内容.

        XPloteStandardItem* childItem2_1 = new XPloteStandardItem(QStringLiteral("武汉"));
        rootItem2->appendRow(childItem2_1);
        //rootItem2->setChild(childItem2_1->index().row(), 1, new XPloteStandardItem(QStringLiteral("步行街")));//在第二列添加数据.

        XPloteStandardItem* childItem2_2 = new XPloteStandardItem(QStringLiteral("园博园")); //注意这里->rootItem2,通过父类设置其所在的行.
        rootItem2->appendRow(childItem2_2);
        //rootItem2->setChild(childItem2_2->index().row(),1,new XPloteStandardItem(QStringLiteral("揽月楼")));

        rootItem2->appendRow(new XPloteStandardItem(QStringLiteral("白云寺")));
    }

}


/// <summary>
/// 右键菜单...
/// </summary>
/// <param name="pos"></param>
void QtTree::on_treeView_customContextMenuRequested(const QPoint& pos)
{
    if (ui.treeView->hasFocus()) {

        menu->exec(this->mapToGlobal(pos));
    }
  
}

  完整的资源下载链接:

http://链接: https://pan.baidu.com/s/1HCHLJmsvV_5CRhqayFhiXg?pwd=hong 提取码: hong 复制这段内容后打开百度网盘手机App,操作更方便哦 --来自百度网盘超级会员v6的分享

 或者关注公众号 我有一座编码屋     回复 QtTree 即可获取链接

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值