我怎样才能将抽象的 class 指针作为 Q_PROPERTY?

How can I have a abstract class pointer as a Q_PROPERTY?

我正在尝试在我的一个扩展 QQuickItems 中使用抽象 class 的实例作为 属性。我有一个基本的 class,像这样:

class VizFactory : public QQuickItem
{
    Q_OBJECT;
    Q_PROPERTY(VisualizationOptions * options READ options WRITE setOptions);

   private:
    VisualizationOptions * m_visualizationOptions;

   public:
    VizFactory(QQuickItem * parent = 0) : QQuickItem(parent) {}
    ~VizFactory() {}

    VisualizationOptions * options() const;
    void setOptions(VisualizationOptions * options);
};

其中 VisualizationOptions 是一个抽象 class,它扩展了一些其他 class,例如 LayoutOptionsFooOptions:

class VisualizationOptions : public QObject
{
    Q_OBJECT

   public:
    VisualizationOptions(QObject * parent = 0) : QObject(parent) {}
    virtual std::string getVisualizationName() const = 0;
};

我在我的主文件中注册所有内容使用:

qmlRegisterUncreatableType<VisualizationOptions>("Wormhole", 1, 0, "VisualizationOptions",
                                                 QString("Cannot create abstract class VisualizationOptions"));
qmlRegisterType<LayoutOptions>("Wormhole", 1, 0, "LayoutOptions");
qmlRegisterType<FooOptions>("Wormhole", 1, 0, "FooOptions");

然后,我尝试通过输入以下内容在 qml 文件中使用它:

VizFactory {
    options: LayoutOptions {
        type: "row"

        FooOptions {}
        LayoutOptions {
            type: "col"
            FooOptions {}
            FooOptions {}
        }
    }
}

但是,我收到的错误来自 qml 文件中定义 options 的那一行:"Cannot assign to non-existent default property"。为什么会这样?我没有正确注册类型吗?我是否错误地实例化了 QML 中的对象?

问题不是由摘要 class 引起的,而是因为 QObject 没有 childItems,不像 QQuickItem 确实有 [=56] =].

如果你使用 QtObject,你会看到同样的东西:

QtObject{
    QtObject{

    }
}

留言:

Cannot assign to non-existent default property

所以有 3 种可能的解决方案:

  • 使 VisualizationOptions 继承自 QQuickItem,因此您可以拥有 children.

  • 不要分配 children,例如您的代码应该工作如下:

    VizFactory{
        options: LayoutOptions{
        }
    }
    
  • 使用QQmlListproperty

我将使用第三种方法展示一个例子:

class VisualizationOptions: public QObject{
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<VisualizationOptions> childOptions READ options)
public:
    using QObject::QObject;
    virtual std::string getVisualizationName() const = 0;
    QQmlListProperty<VisualizationOptions> options(){
        return QQmlListProperty<VisualizationOptions>(this, this,
                                                      &VisualizationOptions::appendOption,
                                                      &VisualizationOptions::optionCount,
                                                      &VisualizationOptions::option,
                                                      &VisualizationOptions::clearOptions);
    }
    void appendOption(VisualizationOptions* p) {
        m_childsoptions.append(p);
    }
    int optionCount() const{
        return m_childsoptions.count();
    }
    VisualizationOptions *option(int index) const{
        return m_childsoptions.at(index);
    }
    void clearOptions() {
        m_childsoptions.clear();
    }
private:
    static void appendOption(QQmlListProperty<VisualizationOptions>* list, VisualizationOptions* p) {
        reinterpret_cast<VisualizationOptions* >(list->data)->appendOption(p);
    }
    static void clearOptions(QQmlListProperty<VisualizationOptions>* list) {
        reinterpret_cast<VisualizationOptions* >(list->data)->clearOptions();
    }
    static VisualizationOptions* option(QQmlListProperty<VisualizationOptions>* list, int i) {
        return reinterpret_cast< VisualizationOptions* >(list->data)->option(i);
    }
    static int optionCount(QQmlListProperty<VisualizationOptions>* list) {
        return reinterpret_cast< VisualizationOptions* >(list->data)->optionCount();
    }
    QVector<VisualizationOptions *> m_childsoptions;
};

*.qml

VizFactory{
    options:
        LayoutOptions{
        type: "row"
        childOptions: [
            FooOptions{},
            LayoutOptions{
                type: "col"
                childOptions: [
                    FooOptions {},
                    FooOptions {}
                ]
            }
        ]
    }
}

您可以在下面link找到完整的代码。