简体   繁体   English

如何在C ++中创建对象并在QML中访问它

[英]How to create object in C++ and access it in QML

I want to use a factory class in C++ to create objects which I can use/access in QML. 我想在C ++中使用工厂类来创建可以在QML中使用/访问的对象。 But how do I access such newly created object in QML? 但是,如何在QML中访问这种新创建的对象? Is this possible with the javascript? JavaScript可以做到这一点吗?

My factory class in C++ creates an employee object which can be either Manager , SalesPerson or Engineer type all derived from Employee . 我的工厂类使用C ++创建了一个employee对象,该对象可以是ManagerSalesPersonEngineer类型,都可以从Employee派生。 Here is the code: 这是代码:

class EmployeeFactory : public QObject
{
    Q_OBJECT
public:
    enum
    {
        MANAGER,
        SALES_PERSON,
        ENGINEER
    };
    explicit EmployeeFactory(QObject *parent = 0);

    Q_INVOKABLE Employee *createEmployee(int type)
    {
        if (type == MANAGER )
        {
            qDebug() << "createEmployee(): Manager created";
            return new Manager;
        }
        else if(type == SALES_PERSON)
        {
            qDebug() << "createEmployee(): SalesPerson created";
            return new SalesPerson;

        }
        else if(type == ENGINEER)
        {
            qDebug() << "createEmployee(): Engineer created";
            return new Engineer;
        }

        qDebug() << "createEmployee(): Nothing created";
        return 0;
    }


signals:

public slots:
};

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    EmployeeFactory * factory = new EmployeeFactory;

    qmlRegisterType<Employee>("MyModel", 1, 0, "employee");

    engine.rootContext()->setContextProperty("factory", factory);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

Now in my QML code, I want to create the employee and access it. 现在在我的QML代码中,我想要创建员工并访问它。

Window {
    visible: true

    MouseArea {
        anchors.fill: parent
        onClicked: {

            // how do I access the return value `employee` here or how
            // do I return/access employee here
            employee e = factory.createEmployee(0) // This doesn't work, result in Expected token ';' error

            // once I have the employee, I would like to set its attributes like
            // e.name: "David"
        }
    }

    Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }
}

If you want a lighter weight version of a QObject, you can make Employee a Q_GADGET. 如果要使用重量更轻的QObject版本,可以将Employee设为Q_GADGET。

https://doc.qt.io/qt-5/qobject.html#Q_GADGET https://doc.qt.io/qt-5/qobject.html#Q_GADGET

If your employees are based on QObject , in that case, you don't need to do anything at all to use the objects in QML, as the meta system will take care. 在这种情况下,如果您的员工基于QObject ,那么您根本不需要做任何事情来使用QML中的对象,因为元系统会很小心。 The downside is that QObject is quite huge, so if you have millions of employees you definitely don't want that. 缺点是QObject非常庞大,因此,如果您有数百万的员工,则绝对不希望这样做。 But for tens of thousands or less it should be OK. 但是数以万计或更少应该没问题。

And since JS is not strongly typed language, it won't be employee e =... but var e = factory.createEmployee(0) If you want to have it typed in properties, you will have to register it as a QML type, it can be as a regular or as a non-creatable, respectively using the qmlRegisterType() and qmlRegisterUncreatableType() functions, the latter is a type you can access and use but not create from QML. 而且由于JS不是强类型语言,因此它不是employee e =...而是var e = factory.createEmployee(0)如果要在属性中键入它,则必须将其注册为QML类型,可以分别使用qmlRegisterType()qmlRegisterUncreatableType()函数作为常规或不可创建函数,后者是可以访问和使用但不能从QML创建的类型。

I assume you have already exposed the factory exposed as a context property. 我假设您已经将工厂公开为上下文属性。

If you don't want your employees to be QObject derived, then you will have to give up on using the objects directly from QML (no, you don't, you can simply use Q_GADGET as vpicaver noted), you can register them to the Qt meta type system with Q_DECLARE_METATYPE() , which will allow you to use them as parameters from QML, but in order to access their data, you will have to use a QObject derived accessor/controller class, which will return the employee data from C++ to QML . 如果您不希望您的员工是QObject派生的,那么您将不得不放弃直接使用来自QML的对象 (不,您可以,如vpicaver所述简单地使用Q_GADGET ),您可以将其注册到具有Q_DECLARE_METATYPE()的Qt元类型系统,该系统将允许您将它们用作QML的参数, 但要访问其数据,您将必须使用QObject派生的访问器/控制器类,该类将从以下位置返回员工数据C ++到QML Or you could use a model to manage, and expose the members as model roles, in that case you need to implement for example a QAbstractListModel . 或者,您可以使用模型进行管理,并将成员公开为模型角色,在这种情况下,您需要实现QAbstractListModel

Also, when creating QObject based objects from C++ and using them in QML, keep in mind object lifetime. 另外,从C ++创建基于QObject的对象并在QML中使用它们时,请记住对象的生存期。 You can explicitly specify whether QML or C++ manages the ownership and lifetime, and I've had my fair share of issues related to QML deleting objects while still in use, leading to crashes, at this point QML ownership seems rather clunky, but the behavior is only exhibited in more complex, highly dynamic scenarios, for "typical" QML usage it is probably ok. 您可以明确指定是由QML还是C ++管理所有权和生存期,我在与QML仍在使用中删除对象有关的问题上有相当一部分,导致崩溃,此时,QML所有权似乎很笨拙,但是行为仅在更复杂,高度动态的情况下才会出现这种情况,对于“典型”的QML使用来说,可能还可以。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM