Qt QMetaObjects并从QWidget转换为QObject

时间:2013-08-21 14:46:48

标签: c++ qt types casting deserialization

我试图制作读取xml文件的代码并从此xml反序列化各种qt控件,并使用QDomDocument进行此操作,并且我想从我的deserealization方法获取QLlist。我有一些麻烦,这里是模板类(.h)文件的一些代码:

 QList<T*> deserialize(QIODevice *input)
 {

        QList<T*> objects = QList<T*>();


        if(_deserializeObject(input, objects)) 
            return objects;

    }
    bool _deserializeObjects(QIODevice* input, QList<QObject*>& list);

和带有deserialize方法的.cpp文件,这里我正在从文件中读取控件标签:

bool Serializer::_deserializeObjects(QIODevice* input,  QList<QObject *> &objects)
{
    QDomDocument doc;
    if (!doc.setContent(input))
        return false;
    QDomElement root= doc.documentElement();

    for(int j = 0; j < root.childNodes().length();j++)
    {


         QObject* object;
         qDebug() << root.tagName();
        if(root.tagName().contains("QGroupBox"))   //  <------- Here i need to determine which control i need to process.
        {
           ????  
        }

       qDebug () << object->metaObject()->className();
       qDebug() << object->metaObject()->propertyCount();

    for(int i = 0; i < object->metaObject()->propertyCount(); i++)
    {

        object->metaObject()->cast()

        QMetaProperty prop = object->metaObject()->property(i);


            QString propName = prop.name();
             if(propName == "objectName")
                 continue;
             QDomNodeList nodeList = root.elementsByTagName(propName);
             if(nodeList.length() < 1)
                continue;
              QDomNode node = nodeList.at(0);
              QVariant value = object->property(propName.toLatin1().data());
              QString v = node.toElement().text();

              if(propName == "x")
              {
                  x = v.toInt();
              }
              else if(propName == "y")
              {
                  y = v.toInt();
              }
              else if(propName == "width")
              {
                  width = v.toInt();
              }
              else if(propName == "height")
              {
                  height = v.toInt();
              }
              if(propName == "geometry")
              {
                   continue;

              }
              object->setProperty(propName.toLatin1().data(), QVariant(v));


    }
    object->setProperty("geometry",QVariant(QRect(x,y,width,height)));
    objects.push_back(object);

    }
    return true;
}

在这部分

  if(root.tagName().contains("QGroupBox"))   //  <------- Here i need to determine which control i need to process.
            {
               ????  
            }

           qDebug () << object->metaObject()->className();
           qDebug() << object->metaObject()->propertyCount();

        for(int i = 0; i < object->metaObject()->propertyCount(); i++)
        {
          ...
        }

我想以某种方式通过名称得到控件的类型,所以问题是,我可以将QGroupBox转换为QObject保存QGroupBox属性,因此QObject metaObject类名称将是QGroupBox,所以我可以传递所有这些属性吗?因为我不想为每种控件类型制作循环。我也是这样的结果:

     QList<QObject *> ds = s.deserialize<Object>((QIODevice*)&f);

然后我可以在循环中传递所有QObject并使用QMetaObject类名并使用qobject_cast将每个对象强制转换为QPushButton,QLabel等吗?

2 个答案:

答案 0 :(得分:1)

QGroupBox是QObject的子类;因此,每个QGroupBox也是一个QObject,因此您可以随时将其视为一个QObject。不需要明确的演员表。

在循环中迭代所有不同的对象-from-from-QObject将执行您想要的操作,只要您调用它们的方法是虚方法(它们可能是它们 - 特别是QObject :: metaObject) ()是一个虚方法,所以你的循环将获得相应的QMetaObject返回,即使它通过QObject指针调用它们的方法。)

(顺便说一下,这个过程的烦人部分可能是你从XML中读取对象类型名称的部分,现在需要实例化那种类型的对象.AFAIK没有好的自动方式要在C ++中做到这一点,所以你能做的最好的是一个工厂函数,它包含一个巨大的switch语句,为你想要实例化的每个类型都有一个单独的case。

答案 1 :(得分:0)

或者,使用正确的工具来完成正确的工作。有可能你在真正构建的内容是用于定义小部件布局等的XML内容.Qt已经有了一个工具,Qt Designer使用XML format UI定义和用于在编译期间实际生成C ++代码的C ++ code generator