将Qt属性与在命名空间中定义的自定义类型一起使用

Ran*_*zen 3 c++ qt qt5

使用自己的类型作为属性类型时,当前存在问题。

我的自定义类型是在名称空间中定义的。当我将其放入全局名称空间时,一切都可以正常工作。

是否可以将名称空间中的自定义类型用作属性值?

这是一个最小的示例(我正在使用Qt5.0和g ++ 4.7.3)

这是test.pro文件:

LANGUAGE  = C++
QT += core gui widgets
TARGET = test
QMAKE_CXXFLAGS += -std=c++11
HEADERS += test.h
SOURCES += test.cpp
Run Code Online (Sandbox Code Playgroud)

这是test.h文件:

#include <QtCore>
#include <QtGui>
#include <QtWidgets>

namespace MyNamespace
{
  struct MyValue
  {
  private:
    QString a;
    int b;

  public:
    MyValue(const QString &a="", int b=0)
      : a(a), b(b)
    {
    }

    bool operator !=(const MyValue &other) const
    {
      return (this->a!=other.a) || (this->b!=other.b);
    }

    friend QDataStream &operator<<(QDataStream &stream, const MyNamespace::MyValue &value);
    friend QDataStream &operator>>(QDataStream &stream, MyNamespace::MyValue &value);
    friend QDebug operator<<(QDebug debug, const MyNamespace::MyValue &value);
  };

  inline QDataStream &operator<<(QDataStream &stream, const MyNamespace::MyValue &value)
  {
    stream << value.a;
    return stream << value.b;
  }

  inline QDataStream &operator>>(QDataStream &stream, MyNamespace::MyValue &value)
  {
    stream >> value.a;
    return stream >> value.b;
  }

  inline QDebug operator<<(QDebug debug, const MyNamespace::MyValue &value)
  {
    return debug << "MyValue("<<value.a<<", "<<value.b<<")";
  }
}

Q_DECLARE_METATYPE(MyNamespace::MyValue)


namespace AnotherNamespace
{
  typedef MyNamespace::MyValue MyValue;

  class MyClass : public QObject
  {
    Q_OBJECT

    Q_PROPERTY(MyValue value READ value WRITE setValue NOTIFY valueChanged)

  public:
    MyValue value()
    {
      return value_;
    }

  public slots:
    void setValue(const MyValue &value)
    {
      if(this->value() != value)
      {
        value_ = value;
        emit valueChanged(value);
      }
    }

  signals:
    void valueChanged(const MyValue &value);

  private:
    MyValue value_;
  };

}
Run Code Online (Sandbox Code Playgroud)

这是test.cpp文件:

#include "test.h"

int main(int argc, char** argv)
{
  QApplication app(argc, argv);

  qRegisterMetaTypeStreamOperators<MyNamespace::MyValue>("MyNamespace::MyValue");


  AnotherNamespace::MyClass myObject;

  myObject.setValue(MyNamespace::MyValue("the answer", 42));

  QMetaObject metaObject = AnotherNamespace::MyClass::staticMetaObject;
  QMetaProperty metaProperty = metaObject.property(metaObject.indexOfProperty("value"));
  QVariant variant = metaProperty.read(&myObject);

  MyNamespace::MyValue value = variant.value<MyNamespace::MyValue>();

  qDebug() << value;


  qDebug() << "\nIt's interesting, that this is working without problems:";
  variant = QVariant::fromValue(MyNamespace::MyValue("2^4", 16));
  value = variant.value<MyNamespace::MyValue>();

  qDebug() << value;


  return 0;
}
Run Code Online (Sandbox Code Playgroud)

此最小示例的输出是

QMetaProperty::read: Unable to handle unregistered datatype 'MyValue' for property 'AnotherNamespace::MyClass::value'
MyValue( "" ,  0 ) 

It's interesting, that this is working without problems: 
MyValue( "2^4" ,  16 ) 
Run Code Online (Sandbox Code Playgroud)

正如alreaday所说的,从最小示例中删除了任何名称空间用法之后,以下输出一切正常

MyValue( "the answer" ,  42 ) 

It's interesting, that this is working without problems: 
MyValue( "2^4" ,  16 ) 
Run Code Online (Sandbox Code Playgroud)

Ran*_*zen 5

在输入问题时,我找到了答案。错误在以下几行

// ...
namespace AnotherNamespace
{
  typedef MyNamespace::MyValue MyValue;

  class MyClass : public QObject
  {
    Q_OBJECT

    Q_PROPERTY(MyValue value READ value WRITE setValue NOTIFY valueChanged)
// ...
Run Code Online (Sandbox Code Playgroud)

使用Q_PROPERTYI时,必须提供完整的typename并注明所有命名空间。所以不要使用

Q_PROPERTY(MyValue value READ value WRITE setValue NOTIFY valueChanged)
Run Code Online (Sandbox Code Playgroud)

我必须用

Q_PROPERTY(MyNamespace::MyValue value READ value WRITE setValue NOTIFY valueChanged)
Run Code Online (Sandbox Code Playgroud)

Qt属性系统似乎无法识别typedef。