Qt - Define global function for QML

2019-06-08 17:17发布

I'm quite knew to Qt and would like to understand if there is a solution for my issue.

I would like to define in C++ a global function that should be called from the QML side. I found a solution on StackOverflow that would let me invoke the function like:

myObject.myFunction();

But I would prefer to avoid the object name like:

myFunction();

that is the same we do, for example, when we need to translate a string:

qsTr("my string");

Is it possible anyway?

标签: c++ qt qml
2条回答
beautiful°
2楼-- · 2019-06-08 17:48

The closest you can get to that is by using a singleton:

import Foo 1.0

Window {
    // ...

    Component.onCompleted: MySingleton.myFunction()
}

Taking the example from the documentation:

// First, define your QObject which provides the functionality.
class SingletonTypeExample : public QObject
{
    Q_OBJECT
    Q_PROPERTY (int someProperty READ someProperty WRITE setSomeProperty NOTIFY somePropertyChanged)

public:
    SingletonTypeExample(QObject* parent = 0)
        : QObject(parent), m_someProperty(0)
    {
    }

    ~SingletonTypeExample() {}

    Q_INVOKABLE int doSomething() { setSomeProperty(5); return m_someProperty; }

    int someProperty() const { return m_someProperty; }
    void setSomeProperty(int val) { m_someProperty = val; emit somePropertyChanged(val); }

signals:
    void somePropertyChanged(int newValue);

private:
    int m_someProperty;
};

// Second, define the singleton type provider function (callback).
static QObject *example_qobject_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
{
    Q_UNUSED(engine)
    Q_UNUSED(scriptEngine)

    SingletonTypeExample *example = new SingletonTypeExample();
    return example;
}

// Third, register the singleton type provider with QML by calling this function in an initialization function.
qmlRegisterSingletonType<SingletonTypeExample>("Qt.example.qobjectSingleton", 1, 0, "MyApi", example_qobject_singletontype_provider);

Then, in QML:

import QtQuick 2.0
import Qt.example.qobjectSingleton 1.0
Item {
    id: root
    property int someValue: MyApi.someProperty

    Component.onCompleted: {
        someValue = MyApi.doSomething()
    }
}
查看更多
祖国的老花朵
3楼-- · 2019-06-08 17:51

You can try to use the setContextObject method of the QQmlContext if the QQmlEngine you are using. I created a minimal Gist which demonstrates the approach.

Basically, you create a custom class deriving from QObject, say, MyApi:

class MyAPI : public QObject
{
    Q_OBJECT
public:
    explicit MyAPI(QObject *parent = nullptr);

    // This method will be visible as function in your QML code:
    Q_INVOKABLE QString makeUpperCase(const QString &text) const;
};

In you main.cpp, set an instance of this class as the context object of the engine's QQmlContext:

QQmlApplicationEngine engine;
engine.rootContext()->setContextObject(new MyAPI(&app));
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

In the QML code, you can now access all properties, signals, slots and Q_INVOKABLE methods of the MyAPI class:

Window {
    visible: true
    width: 640
    height: 480

    // Call the `makeUpperCase` method of the context object:
    title: makeUpperCase("Hello World")
}
查看更多
登录 后发表回答