QVariant 存取任意类型的指针 、自定义数据类型(****)

目录

QVariant的用法 (***)

QVariant 存放指针

QVariant 存取任意类型的指针

QVariant保存指针数据 (**)

----------------------------------------------

测试代码 1:直接调用

测试代码 2:使用模板

----------------------------------------------

问题:

使用指针的麻烦:在代码运行使用之前,必须保证其中的数据有效。。

----------------------------------------------------

要点:

MainWindow *p;

QVariant v_mwPointorQVariant::fromValue((void *) p);   // 存放 + 生成指针

MainWindow* pWmVarInForm = (MainWindow*)v_mwPointor.value<void*>();  // 获取指针

官方手册:

[static] QVariant QVariant::fromStdVariant(const std::variant<Types...> &value)
Returns a QVariant with the type and value of the active variant of value. If the active type is std::monostate a default QVariant is returned.
Note: With this method you do not need to register the variant as a Qt metatype, since the std::variant is resolved before being stored. The component types should be registered however.
This function was introduced in Qt 5.11.
See also fromValue().

 
[static] QVariant QVariant::fromValue(const T &value)
Returns a QVariant containing a copy of value. Behaves exactly like setValue() otherwise.
Example:

  MyCustomStruct s;
  return QVariant::fromValue(s);

Note: If you are working with custom types, you should use the Q_DECLARE_METATYPE() macro to register your custom type.
See also setValue() and value().

T QVariant::value() const
Returns the stored value converted to the template type T. Call canConvert() to find out whether a type can be converted. If the value cannot be converted, a default-constructed value will be returned.
If the type T is supported by QVariant, this function behaves exactly as toString(), toInt() etc.
Example:

  QVariant v;

  MyCustomStruct c;
  if (v.canConvert<MyCustomStruct>())
      c = v.value<MyCustomStruct>();

  v = 7;
  int i = v.value<int>();                        // same as v.toInt()
  QString s = v.value<QString>();                // same as v.toString(), s is now "7"
  MyCustomStruct c2 = v.value<MyCustomStruct>(); // conversion failed, c2 is empty

If the QVariant contains a pointer to a type derived from QObject then T may be any QObject type. If the pointer stored in the QVariant can be qobject_cast to T, then that result is returned. Otherwise nullptr is returned. Note that this only works for QObject subclasses which use the Q_OBJECT macro.
If the QVariant contains a sequential container and T is QVariantList, the elements of the container will be converted into QVariants and returned as a QVariantList.

  QList<int> intList = {7, 11, 42};

  QVariant variant = QVariant::fromValue(intList);
  if (variant.canConvert<QVariantList>()) {
      QSequentialIterable iterable = variant.value<QSequentialIterable>();
      // Can use foreach:
      foreach (const QVariant &v, iterable) {
          qDebug() << v;
      }
      // Can use C++11 range-for:
      for (const QVariant &v : iterable) {
          qDebug() << v;
      }
      // Can use iterators:
      QSequentialIterable::const_iterator it = iterable.begin();
      const QSequentialIterable::const_iterator end = iterable.end();
      for ( ; it != end; ++it) {
          qDebug() << *it;
      }
  }

See also setValue(), fromValue(), canConvert(), and Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE().

----------------------------------------------------

参考:

QVariant 存取任意类型的指针 、自定义数据类型(****)
https://blog.csdn.net/ken2232/article/details/131733264

开放 Qt窗口的 this指针 的方法汇总 (*****)
https://blog.csdn.net/ken2232/article/details/129634701

----------------------------------------------------

测试代码 1:直接调用

mainwindow.cpp

    //QVariant v_mwPointor; //修改为:全局变量。或静态成员?
    MainWindow *p;
    p =this;
    v_mwPointor =  QVariant::fromValue((void *) p);  //VPtr<MainWindow>::asQVariant(p);

   
    //
    qDebug()<<"p =this : 11 : "<<p;
    qDebug()<<"v / v_mwPointor : 22 :  "<<v_mwPointor;

   

// ?????

    Form *abc =new Form; // pVar在词句之前执行。
    abc->show();

form.cpp

    //获取
    MainWindow* pWmVarInForm=(MainWindow*)v_mwPointor.value<void*>();
    qDebug()<<"extern QVariant v_mwPointor : "<<pWmVarInForm;

    pWmVarInForm->ui->pushButton->setText("abcde");

测试代码 2:使用模板

包含在下面的内容里。

mainwindow.cpp

template <class T> class VPtr
{
public:
    static T* asPtr(QVariant v)
    {
        return  (T *) v.value<void *>();
    }

    static QVariant asQVariant(T* ptr)
    {
        return QVariant::fromValue((void *) ptr);
    }
};


class MainWindow : public QMainWindow
{
    Q_OBJECT

mainwindow.cpp

QVariant v_mwPointor;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    
    Form *abc =new Form; // pVar在词句之前执行。
    abc->show();

    MainWindow *p;
    p =this;
    v_mwPointor = VPtr<MainWindow>::asQVariant(p);
    qDebug()<<"v / v_mwPointor :  "<<v_mwPointor;
}

form.cpp
void Form::on_pushButton_clicked()
{
    extern QVariant v_mwPointor;
    MainWindow *pWmVarInForm = VPtr<MainWindow>::asPtr(v_mwPointor); //成员函数获取 mW指针

 
    //MainWindow* pWmVarInForm=(MainWindow*)v_mwPointor.value<void*>(); //直接变量获取 mW指针
    qDebug()<<"pWmVarInForm : "<<pWmVarInForm;

    pWmVarInForm->ui->pushButton->setText("abcde");
    //p1_mwPointor->close();
}

----------------------------------------

参考:

QVariant 存取任意类型的指针 、自定义数据类型
https://blog.csdn.net/ken2232/article/details/131733264

QVariant类
https://blog.csdn.net/ken2232/article/details/131732801

Qt 子对象引用mainwindow指针的巧妙方法 (***)
https://blog.csdn.net/ken2232/article/details/129638483


Qt里通过传递函数指针实现动态绑定信号/槽 (**)
https://blog.csdn.net/ken2232/article/details/131566404

----------------------------------------------------

QVariant 存取任意类型的指针

QVariant v = QVariant::FromValue((void *) yourPointerHere);
yourPointer = (YourClass *) v.value<void *>();

官方手册:

[static] QVariant QVariant::fromValue(const T &value)
Returns a QVariant containing a copy of value. Behaves exactly like setValue() otherwise.
Example:

  MyCustomStruct s;
  return QVariant::fromValue(s);

Note: If you are working with custom types, you should use the Q_DECLARE_METATYPE() macro to register your custom type.
See also setValue() and value().

示例:存放指针

(已验证****)

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

            

    // need 1: 声明为全局变量:QVariant pVar;

    //保存
    pVar=QVariant::fromValue((void*)this);
    qDebug()<<"pVar in MainWindow : "<<pVar;

        
    Form *abc =new Form; // pVar在此句之前执行。
    abc->show();
}

form.cpp

extern QVariant pVar;
void Form::on_pushButton_clicked()
{
    // need 1: #include "ui_mainwindow.h"
    // need 2: extern QVariant pVar;

                 

    //获取
    MainWindow* pVarInForm=(MainWindow*)pVar.value<void*>();
    qDebug()<<"extern var : "<<pVarInForm;

         

    pVarInForm->ui->pushButton->setText("abcde");  //MainWindow需要开放 ui指针
    //pVarInForm->close();
}

==============================
 

采用 QVariant来存放指针,似乎使用也来越广泛、越来越重要了?

在 Qt 6.0之后,就有了一个专门的来来处理

QVariantPointer Class

https://doc.qt.io/qt-6/qvariantpointer.html

QVariantPointer Class

template <typename Pointer> class QVariantPointer

QVariantPointer is a template class that emulates a pointer to QVariant based on a pointer. More...

Header:#include <QVariantPointer>
CMake:find_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(mytarget PRIVATE Qt6::Core)
qmake:QT += core
Since:Qt 6.0

Public Functions

QVariantPointer(const Pointer *pointer)
QVariantRef<Pointer>operator*() const
Pointeroperator->() const

Detailed Description

QVariantConstPointer wraps a pointer and returns QVariantRef to it from its operator*(). This makes it suitable as replacement for an actual pointer. We cannot return an actual pointer from generic iterators as the iterators don't hold an actual QVariant.

Member Function Documentation

[explicit] QVariantPointer::QVariantPointer(const Pointer *pointer)

Constructs a QVariantPointer from the given pointer.

QVariantRef<Pointer> QVariantPointer::operator*() const

Dereferences the QVariantPointer to a QVariantRef.

Pointer QVariantPointer::operator->() const

Dereferences and returns the pointer. The pointer is expected to also implement operator->().

==============================

QVariant的用法 (***)

https://blog.csdn.net/xiaopei_yan/article/details/81410092

前言

QVariant这个类很神奇,或者说方便。很多时候,需要几种不同的数据类型需要传递,如果用结构体,又不大方便,容器保存的也只是一种数据类型,而QVariant则可以统统搞定。

介绍

帮助文档上说:The QVariant class acts like a union for the most common Qt data types.。

QVariant 这个类型充当着最常见的数据类型的联合。QVariant 可以保存很多Qt的数据类型,包括QBrush、QColor、QCursor、QDateTime、QFont、QKeySequence、 QPalette、QPen、QPixmap、QPoint、QRect、QRegion、QSize和QString,并且还有C++基本类型,如 int、float等。

当然,如果支持的类型没有想要的,没关系,QVariant也可以支持自定义的数据类型。被QVariant存储的数据类型需要有一个默认的构造函数和一个拷贝构造函数。为了实现这个功能,首先必须使用Q_DECLARE_METATYPE()宏。通常会将这个宏放在类的声明所在头文件的下面:

Q_DECLARE_METATYPE(MyClass)

示例

(1)支持的类型。对于QVariant支持的类型,可直接赋值,但是取值时,对于存入的是什么类型,取出也要为这个类型。

        QVariant var;
        var.setValue(12);
        int data=var.toInt();

        QVariant var=12;
        int data=var.toInt();

(2)对于不支持的类型,如自己定义的结构体。由于Qt都是基于元对象系统,故要在头文件里面要注册此类属于元类型。存储用到了QVariant QVariant::fromValue(const T &value) 或 void QVariant::setValue(const T &value)。获取用到了

T QVariant::value() const,在这之前一般要bool QVariant::canConvert(int targetTypeId) const先用进行判断,是否可以转换。例子如下:

.h文件声明

     
    struct MyClass{
        int id;
        QString name;
    };
    Q_DECLARE_METATYPE(MyClass)

.cpp文件定义

    //存储数据
        MyClass myClass;
        myClass.id=0;
        myClass.name=QString("LiMing");
     
        data[0]=QString("ddd");
        data[1]=123;
        data[3]=QVariant::fromValue(myClass);
     
     
    //获取数据
        QString str=data.value(0).toString();
        int val=data.value(1).toInt();
     
        if(data[3].canConvert<MyClass>())
        {
            MyClass myClass=data[3].value<MyClass>();
            int id=myClass.id;
            QString name=myClass.name;
        }

(3)对于不支持的C++基础数据类型,如 short  char,先通过toInt()转化为int类型,然后再将int转为其原本的数据类型。

     
    //-------------------------------char--------------------------
    //char -> QVariant
    QVariant var='B';
    qDebug()<<var;   //QVariant(int, 66)
     
     
    // QVariant ->char
    char channel=var.toInt();
     
    //------------------------------short--------------------------
    //short -> QVariant
    short dataType=12;
    QVariant var2=dataType;
    qDebug()<<var2;      //QVariant(int, 12)
     
     
    //QVariant -> short
    short temp=(short)var2.toInt();

(4)保存指针,感觉这个比较强大,也比较容易用到。如

        //保存
        QVariant var=QVariant::fromValue((void*)event);
        
        //获取
        QPaintEvent* e=(QPaintEvent*)var.value<void*>();

(5)还有种写法,用QVariant的构造函数QVariant(int typeId, const void *copy)。

虽然不常用,特别是指针类型,即             

QMetaType::VoidStar, 和 QMetaType::QObjectStar,

一般还是用fromValue。但是还是以存取QObject*为例补充下吧,

起码知道写法。

        QObject* obj=new QObject;
        obj->setObjectName("myObj");
     
        //保存
        QVariant var=QVariant(QMetaType::QObjectStar,&obj);
     
        //提取
        QObject* myobj=qvariant_cast<QObject*>(var);
        if(myobj!=NULL)
            qDebug()<<myobj->objectName();
     
        obj->deleteLater();

(6) QVariant与json之间的各种转换

QVariant与Json的各种纠葛——Qt_十年之少的博客-CSDN博客

警告:

不要盲目的随便使用QVariant之类,它比较消耗内存和影响处理速度!!!

结束语

程序中有很多小点,存储着很大的智慧,就如QVariant就是如此。

————————————————
版权声明:本文为CSDN博主「十年之少」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xiaopei_yan/article/details/81410092

==============================

QVariant保存指针数据 (***)

https://www.cnblogs.com/alleyonline/p/4781304.html

QVariant 默认无法保存指针数据,因为以 void *为参数的QVariant构造函数是私有的

但通过QT提供的Meta Type机制,可以将任意指针存放到QVariant中。

需要使用Q_DECLARE_METATYPE宏注册类型。

Q_DECLARE_METATYPE(QStandardItemModel*)

之后,就可以使用QVariant::fromValue存放数据,使用QVariant::value获取数据了。

return QVariant::fromValue(model_);

//....

QStandardItemModel* model = some_value.value();

使用QVariant和标识项目中数据类型的Qt::ItemDataRole,可以方便地将任意数据存放进QT提供的预定义模型中。

比如,在同一个QStandardItem中使用不同的Role,存放多个数据。

自定义的数据角色

enum CustomItemRole

{

    LevelModelRole =  Qt::UserRole + 1000,

    TimeModelRole = Qt::UserRole + 1010,

    FileModelRole = Qt::UserRole + 1020

};

存放特定角色的数据

type_of_level_item->setData(QVariant::fromValue(level_list_model),LevelModelRole);

获取特定角色的数据

QVariant data = item->data(Qt::LevelModelRole);

因为QStandardItemModel以行为单位建立树形结构,所以要实现更复杂的树形结构,可以使用自定义的DataRole来存储数据。

==================================

QVariant 存放指针

QVariant v = QVariant::fromValue((void *) yourPointerHere);
yourPointer = (YourClass *) v.value<void *>();


--------------------------------------------------------------------------------------------------

You can store many types of data into QVariant, like int, string, etc. Also you can store pointers, but only pointers to void (void ). But what happens when you want to set a property of a object to a instance of class, with setProperty, and after that, you want to retrieve that property? QVariant accepts void , so you can do something like the following, to store it into QVariant:

QVariant v = QVariat::FromValue((void *) yourPointerHere);

and then something like this, in order to retrieve it back from QVariant://你也可以恢复到指针

yourPointer = (YourClass *) v.value<void *>();

Having this done each time you have to get the property or set the property is a bit tendentious. We can make this more friendly, using templates:

template <class T> class VPtr
{
public:
    static T* asPtr(QVariant v)
    {
        return  (T *) v.value<void *>();
    }
    
    static QVariant asQVariant(T* ptr)
    {
        return QVariant::fromValue((void *) ptr);
    }
};

So how do you use this?

Assuming you have a class MyClass, and you want to store a pointer to this class as a property of a QWidget, or any QObject, or you want to convert it to QVariant,

you can do the following:

MyClass *p;
QVariant v = VPtr<MyClass>::asQVariant(p);
MyClass *p1 = VPtr<MyClass>::asPtr(v);

I think this is more developer friendly than having to write each time those conversion code sequences.

转载:http://ju.outofmemory.cn/entry/179497

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
QVariantQt 中的一个通用的值类型,可以用来存储各种类型的数据,包括基本类型、用户自定义类型、甚至指针等。但是,如果要在 QVariant 中存储用户自定义类型的对象,需要实现 QVariant::Type 类型的转换函数。这个转换函数的基本要求是将自定义类型转换为 QVariant,并将 QVariant 转换回自定义类型。这个过程可以称为类型注册,它将自定义类型与 QVariant 类型关联起来,使得 QVariant 在遇到这种类型时可以正确地进行操作。 要完成 QVariant 自定义类型的实现,首先需要了解 QVariant 的内部实现机制。QVariant 内部使用了一个类似于 Variant 类的黑盒子来存储各种类型的值,在存储、获取、转换值时,需要使用 QVariant 内部提供的接口来进行操作。 接着,将自定义类型与 QVariant 类型进行关联,用户需要实现 QVariant::Type 类型的转换函数。这个函数的实现方式取决于自定义类型的实现机制,可以使用 QVariant 提供的模板类型来序列化与反序列化自定义类型,或者手动实现这些转换函数。 完成了自定义类型与 QVariant 类型之间的关联,就可以将自定义类型的对象存储到 QVariant 中了。存储时,需要将自定义类型的对象转换为 QVariant 类型,这里需要使用 QVariant::fromValue 函数。获取时,则需要将 QVariant 类型转换为自定义类型,这里可以使用 QVariant::value 函数,并传入自定义类型的 TypeId。 总之,QVariant 自定义类型的实现需要实现 QVariant::Type 类型的转换函数,并将自定义类型与 QVariant 类型关联起来,实现自定义类型与 QVariant 类型之间的转换。在实际的应用中,需要根据自定义类型的实现机制来选择相应的序列化与反序列化方式,以便正确存储、获取自定义类型的对象。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值