简体   繁体   中英

Register a C++ abstract class in a QML plugin and refer to it from QML


I'm writing a Qt app.
I've separated my app to a QML frontend and a C++ plugin backend.
In my C++ plugin I have a Session abstract class that I would like to expose to QML and I also have a few implementations of that class.
I would like my QML frontend to only know of the Session class and not be bothered with the specifics of which kind of session it is.
I tried a few variations of qmlRegister* to register my Session type with QML but either Session needs to be concrete (as in qmlRegisterType's case) or it registers fine but I simply cannot refer to the Session type from QML as in property Session session without even instantiating a Session from QML.
Does anyone know how I should approach this?

UPDATE :
An example of what didn't work:
In main.cpp:

char const* const uri = "com.nogzatalz.Downow";
qmlRegisterUncreatableType<downow::Session>(uri, 1, 0, "Session", "Abstract type");

In DowNow.qml:

import QtQuick 2.0
import com.nogzatalz.Downow 1.0

Item {
    property Session session
}

I got this working with qmlRegisterInterface . My virtual call is InputDeviceConfigurator:

class InputDeviceConfigurator : public QObject
{
    Q_OBJECT
public:
    explicit InputDeviceConfigurator(QObject *parent = 0);
    Q_INVOKABLE virtual QString deviceId() = 0;
}

I register it as follows:

qmlRegisterInterface<InputDeviceConfigurator>( "InputDeviceConfigurator" );

And then use an inherited class JoystickConfigurator:

class JoystickConfigurator : public InputDeviceConfigurator
{
public:
    JoystickConfigurator( JoystickDevice * device );

    // InputDeviceConfigurator interface
    virtual QString deviceId() override;
}

And than I can use it:

 Component.onCompleted: console.log( UserInputManagement.getConfigurator().deviceId() )

UserInputManagement is just a Singleton with:

Q_INVOKABLE InputDeviceConfigurator  * getConfigurator();

As far I know it's impossible to create a variable using an abstract class as a definition.

You can declare the session variable as a QtObject in the qml code, you will just loose the auto-completion feature of qtcreator.
However all property declare with Q_PROPERTY macro and all Q_INVOKABLE functions will still be available at runtime.

If you want to have nearly the same semantic, I suggest you create a singleton C++ class that you register to QML using qmlRegisterSingletonType and have that class carry you "session" variable. Then keep the qmlRegisterUncreatableType on your Session abstract class, that way in qml code you will be able to write something like :

MySingleton.session

And keep the auto-completion for qml within qtcreator.
As a bonus you will also be able to create a signal "SessionChanged" if your users can login / logout multiple times without restarting the app.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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