QtTreePropertyBrowser使用

简单介绍

QtPropertyBrowser是一套用以显示属性的控件,QtDesigner右边的属性编辑器用的就是该控件

 

 

安装

在安装Qt时,如果选择了安装源码,即下图选中的Sources,那么在Qt的安装目录下是包含了QtPropertyBrowser的完整源码的

 

QtPropertyBrowser的源码位置目录如下,在Src的qttools的shared目录下

 

如果没有安装源码,也可以在github上下载,地址如下:

 

 

使用

1. 在QtCreator中,新建个Qt项目并在.pro文件中加入这句即可引用QtPropertyBrowser

include($$[QT_INSTALL_PREFIX]/../Src/qttools/src/shared/qtpropertybrowser/qtpropertybrowser.pri)
// 把其当做一个普通QWidget插入布局即可显示
auto property = new QtTreePropertyBrowser(this);
main_layout->addWidget(property);

效果如下图所示,但是因为没有设置内容,所以控件里面是空的。 

 

 

2. 在vs中,可以将该模块的所有.h/.cpp文件添加到现有项中

但是此时生成解决方案的话,会出现“使用了未定义类型“QtVariantPropertyManagerPrivate...”的错误

这个问题的原因和解决方法如下面文字所述:

The problem is your project is set up to compile the generated moc_XXX.cpp files for the qtpropertybrowser headers .
In this case they are included at the end of qtXXX.cpp files and are not meant to be compiled separately, as they make use of the private implementation in the ccp.

To fix this, in VS, select all the qtXXX.h files from qtpropertybrowser (except for the qtXXX_p.h). Right click and select Properties.
In the property page go to Configuration Properties -> Qt Meta-Object-Compiler -> moc and set Dynamic C++ Source to Disable. This will exclude generated moc_ files from direct compilation. They will be compiled as an include in the cpp files from qtpropertybrowser, the way they were meant to be.

解决方法:将除了qtpropertybrowserutils_p.h之外的头文件全部选中并右击,在配置属性中更改moc的Dynamic C++ Source为Disable即可

 

 

 

填充数据

首先包含以下三个头文件

#include <qttreepropertybrowser.h>
#include <qtvariantproperty.h>
#include <qtpropertymanager.h>
  • QtTreePropertyBrowser,该控件的主体,本身是基于一个QTreeWidget实现而来的;
  • QtVariantPropertyManager,用于管理控件中的属性,一般只有一个;
  • QtVariantProperty,控件中具体的属性条目,可以有很多条,如下图中的“Bool:True”是一个条目, “Double:12.34”是一个条目;

具体代码如下:

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <qttreepropertybrowser.h>
#include <qtvariantproperty.h>
#include <qtpropertymanager.h>

#include <QHBoxLayout>
#include <QVBoxLayout>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    propertyBrowser = new QtTreePropertyBrowser(this);
    QtVariantPropertyManager *m_pVarManager = new QtVariantPropertyManager(propertyBrowser);

    QtVariantProperty *item = m_pVarManager->addProperty(QVariant::Int, QStringLiteral("Int: "));
    item->setValue(100);
    propertyBrowser->addProperty(item);

    item = m_pVarManager->addProperty(QVariant::Bool, QStringLiteral("Bool: "));
    item->setValue(true);
    propertyBrowser->addProperty(item);

    item = m_pVarManager->addProperty(QVariant::Double, QStringLiteral("Double: "));
    item->setValue(12.34);
    propertyBrowser->addProperty(item);

    item = m_pVarManager->addProperty(QVariant::String, QStringLiteral("String: "));
    item->setValue(QStringLiteral("TestTest"));
    propertyBrowser->addProperty(item);

    auto main_layout = new QVBoxLayout();
    main_layout->addWidget(propertyBrowser);
    this->centralWidget()->setLayout(main_layout);
}

MainWindow::~MainWindow()
{
    delete ui;
}

 

除此之外,PropertyBrowser中还具有分组功能

代码展示如下:

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <qttreepropertybrowser.h>
#include <qtvariantproperty.h>
#include <qtpropertymanager.h>

#include <QHBoxLayout>
#include <QVBoxLayout>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    propertyBrowser = new QtTreePropertyBrowser(this);
    QtVariantPropertyManager* m_pVarManager = new QtVariantPropertyManager(propertyBrowser);

    // group 1 ----------------------------------------------------------------------------------------------------------
    QtProperty *groupItem1 = m_pVarManager->addProperty(QtVariantPropertyManager::groupTypeId(),QStringLiteral("分组1"));

    QtVariantProperty *item = m_pVarManager->addProperty(QVariant::Int, QStringLiteral("Int: "));
    item->setValue(100);
    groupItem1->addSubProperty(item);

    item = m_pVarManager->addProperty(QVariant::Bool, QStringLiteral("Bool: "));
    item->setValue(true);
    groupItem1->addSubProperty(item);

    item = m_pVarManager->addProperty(QVariant::Double, QStringLiteral("Double: "));
    item->setValue(12.34);
    groupItem1->addSubProperty(item);

    item = m_pVarManager->addProperty(QVariant::String, QStringLiteral("String: "));
    item->setValue(QStringLiteral("TestTest"));
    groupItem1->addSubProperty(item);

    propertyBrowser->addProperty(groupItem1);


    // group 2 -----------------------------------------------------------------------------------------------------------
    QtProperty *groupItem2 = m_pVarManager->addProperty(QtVariantPropertyManager::groupTypeId(),QStringLiteral("分组2"));

    QtVariantProperty *item2 = m_pVarManager->addProperty(QVariant::String, QStringLiteral("Position"));
    item2->setValue("100, 100, 100");
    groupItem2->addSubProperty(item2);

    item2 = m_pVarManager->addProperty(QVariant::Double, QStringLiteral("Width"));
    item2->setValue(300.0);
    groupItem2->addSubProperty(item2);

    item2 = m_pVarManager->addProperty(QVariant::Double, QStringLiteral("Height"));
    item2->setValue(200.0);
    groupItem2->addSubProperty(item2);

    propertyBrowser->addProperty(groupItem2);

    auto main_layout = new QVBoxLayout();
    main_layout->addWidget(propertyBrowser);
    this->centralWidget()->setLayout(main_layout);
}

MainWindow::~MainWindow()
{
    delete ui;
}

 

 

编辑功能

实现属性值的编辑功能,需要引入QtVariantEditorFactory,为QtVariantPropertyManager对象设置一个编辑工厂即可

 

#include <qteditorfactory.h>

//...省略...//

propertyBrowser = new QtTreePropertyBrowser(this);
QtVariantPropertyManager * m_pVarManager = new QtVariantPropertyManager(propertyBrowser);
QtVariantEditorFactory * edit_factory = new QtVariantEditorFactory(propertyBrowser);
propertyBrowser->setFactoryForManager(m_pVarManager, edit_factory);

 

当属性被编辑修改时,是会产生信号的,信号如下

QtVariantPropertyManager::valueChanged(QtProperty *property, constQVariant &value)

我们需要定义一个QMap来存储QtProperty和每个条目的名字之间的对应关系,在创建每个条目的时候存储这两个参数。再创建一个槽函数,参数为信号对应的参数

// .h文件中
public slots:
    void PropertyValueChanged(QtProperty *property, const QVariant &value);

private:
    QPointer<QtTreePropertyBrowser> propertyBrowser;
    QMap<QtProperty*, QString> property_dic;


// .cpp文件中
QtVariantProperty *item2 = m_pVarManager->addProperty(QVariant::String, QStringLiteral("Position"));
item2->setValue("100, 100, 100");
property_dic[item2] = "Position";
groupItem2->addSubProperty(item2);

item2 = m_pVarManager->addProperty(QVariant::Double, QStringLiteral("Width"));
item2->setValue(300.0);
property_dic[item2] = "Width";
groupItem2->addSubProperty(item2);

// 信号槽链接
connect(m_pVarManager, &QtVariantPropertyManager::valueChanged, this, &MainWindow::PropertyValueChanged);

// 信号发出时对应的槽函数
void MainWindow::PropertyValueChanged(QtProperty *property, const QVariant &value)
{
    QString property_name = property_dic[property];
    QMessageBox::information(this, property_name, value.toString());
}

 效果如下:

 

 

 

更改列数

有时一个条目不光包括着名字和值,还有单位,比如长度属性,可能还包含单位信息如米,但是现在的PropertyBrowser只含有两列。该控件的本质是一个QTreeWidget,所以为了实现三列的功能,可以在源码中稍作修改,将QTreeWidget的列数改为3。

查看QtTreePropertyBrowser的源码如下,在init()函数中可以清晰得看出这个控件的本体是个QTreeWidget,并且它的表头标签也可以在这里修改,比如改成中文的表头

效果如下:

 

现在是正常出现了第三列的,但是第三列的数据空白,继续往下翻源码,会发现填充数据是在updateItem()函数中实现的,同样在这里稍作修改设置第三列的单位就可以了。

 

 

 

  • 14
    点赞
  • 104
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值