QObject的setUserData和setProperty——Qt

本文对比了Qt中setUserData与setProperty两种存储界面数据的方法。setUserData要求数据继承自QObjectUserData,使用不便;setProperty则更为灵活,接受QVariant类型,更适合作为现代Qt开发的标准实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

很多时候需要界面存储一些数据或信息,这样可以根据这些数据或信息来了解或获取点什么。可以说给界面增加一个标记,让我们更容易辨识。

我之前一直习惯给列表项QListWidgetItem或者树项QTreeWidgetItem携带一些数据,比如id,用setData来实现。所以这次就想QWidget有没有类似的方法,结果就找到了setUserData。后来在mac os中重新编译时,发现setUserData不可用了,建议用setProperty替换。

 

用法

我现在用的Qt的版本是Qt5.9 windows,方法setUserData已经在官方的帮助文档中看不到了,只能在.h中看到他的声明;而setProperty则可以在帮助文档中看到。

下面是qobject.h文件中的声明,QT_NO_PROPERTIES和QT_NO_USERDATA应该是为了版本的兼容。

#ifndef QT_NO_PROPERTIES
    bool setProperty(const char *name, const QVariant &value);
    QVariant property(const char *name) const;
    QList<QByteArray> dynamicPropertyNames() const;
#endif // QT_NO_PROPERTIES

#ifndef QT_NO_USERDATA
    static uint registerUserData();
    void setUserData(uint id, QObjectUserData* data);
    QObjectUserData* userData(uint id) const;
#endif // QT_NO_USERDATA

 setUserData的用法

通过声明我们可以看到:要想设置用户的数据,数据则必须继承QObjectUserData,我用了结构体来存储数据

struct LevelValue:QObjectUserData {
  int iLevel;
  int iFormType; //界面类型
};

然后新建此数据对象,然后将此对象的指针交由此保存。

    //设置界面等级
    LevelValue* data=new LevelValue;
    data->iLevel=2;
    data->iFormType=0;
    this->setUserData(Qt::UserRole,data);

然后同userData来获取数据,根据数据进行相应的处理。

    QWidget* pCurWidget=ui->formStacked->widget(index);
    LevelValue *data=(LevelValue*)pCurWidget->userData(Qt::UserRole);
    if(data!=NULL)
    {
        int iType=data->iFormType;
        m_latestForms[iType]=pCurWidget;
    }

 

setProperty的用法

通过上面的介绍多少觉得setUserData的方法有些别扭,特别是数据必须要继承QObjectUserData,挺不方便的,而且仅此用得到这个类吧,感觉也不通用,所以他被换掉也是有原因的。

而setProperty则方便很多:它的数据是QVariant 类型的,这个类型就像var一样的好用(这个类型我在以前的博客有介绍,点这里)。若自定义的类型记得用宏Q_DECLARE_METATYPE注册到元对象系统,枚举用Q_ENUMS注册。

通过名字,可以了解到这是设置属性,Qt中有庞大的属性系统,这个方法是动态添加属性。若想详细的了解Qt属性系统,可以通过亮大的博客了解。注意的是:如果QObject中一个指定名称的属性已经存在,并且如果给定的值与属性的类型兼容,那么,值就被存储到属性中,然后返回true。如果值与属性类型不兼容,属性的值就不会发生改变,会返回false。但是如果QObject中一个指定名称的属性不存在(例如:未用Q_PROPERTY()声明),一个带有指定名称和值的新属性就被自动添加到QObject中,但是依然会返回false。这意味着返回值不能用于确定一个属性是否被设置值,除非事先知道这个属性已经存在于QObject中。

 

    //.h声明
    struct LevelValue {
      int iLevel;
      int iFormType; 
    };
    Q_DECLARE_METATYPE(LevelValue) 
    LevelValue data;
    data.iLevel=2;
    data.iFormType=0;
    
    QVariant var=QVariant::fromValue(data);
    this->setProperty("LevelValue",var);
  QVariant var=pCurWidget->property("LevelValue");
  //可加判断
  if(var.canConvert<LevelValue>())
  {
      LevelValue data=var.value<LevelValue>();
  }
    

结束语

以后还是用setProperty吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

十年之少

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

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

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

打赏作者

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

抵扣说明:

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

余额充值