Javascript函数作为从c ++定义的QML属性

Ayb*_*gür 1 javascript c++ function-pointers qml qtquick2

我在c ++中定义了以下QML对象:

class MyObj : public QQuickItem {
    Q_OBJECT
    Q_PROPERTY(QVariant func MEMBER func)

public slots:
    void callFunc(){
        //Call function pointed by "func" somehow
    }

private:
    QVariant func;
};
Run Code Online (Sandbox Code Playgroud)

在QML中我使用MyObj如下:

MyObj{
    func: function test(){ console.log("Hi!"); }

    Button{
        text: "Call func"
        onClicked: parent.callFunc()
    }
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

Unable to assign a function to a property of any type other than var.
Run Code Online (Sandbox Code Playgroud)

我不明白,是不是一个QVariant应该是相同的属性property var?这样做的正确方法是什么?

Mit*_*tch 5

你可以用QJSValue它.Qt Quick Controls 2's SpinBox 做了类似事情:

Q_PROPERTY(QJSValue textFromValue READ textFromValue WRITE setTextFromValue NOTIFY textFromValueChanged FINAL)
Run Code Online (Sandbox Code Playgroud)

它的getter和setter实现如下:

QJSValue QQuickSpinBox::textFromValue() const
{
    Q_D(const QQuickSpinBox);
    if (!d->textFromValue.isCallable()) {
        QQmlEngine *engine = qmlEngine(this);
        if (engine)
            d->textFromValue = engine->evaluate(QStringLiteral("function(value, locale) { return Number(value).toLocaleString(locale, 'f', 0); }"));
    }
    return d->textFromValue;
}

void QQuickSpinBox::setTextFromValue(const QJSValue &callback)
{
    Q_D(QQuickSpinBox);
    if (!callback.isCallable()) {
        qmlInfo(this) << "textFromValue must be a callable function";
        return;
    }
    d->textFromValue = callback;
    emit textFromValueChanged();
}
Run Code Online (Sandbox Code Playgroud)

如果没有给出(或者值实际上不是函数),则getter提供默认函数实现.

该函数用于 允许用户返回给定输入值的自定义文本:

text: control.textFromValue(control.value, control.locale)
Run Code Online (Sandbox Code Playgroud)

文档为例,这里是你如何分配/覆盖函数:

SpinBox {
    id: spinbox
    from: 0
    value: 110
    to: 100 * 100
    stepSize: 100
    anchors.centerIn: parent

    property int decimals: 2
    property real realValue: value / 100

    validator: DoubleValidator {
        bottom: Math.min(spinbox.from, spinbox.to)
        top:  Math.max(spinbox.from, spinbox.to)
    }

    textFromValue: function(value, locale) {
        return Number(value / 100).toLocaleString(locale, 'f', spinbox.decimals)
    }

    valueFromText: function(text, locale) {
        return Number.fromLocaleString(locale, text) * 100
    }
}
Run Code Online (Sandbox Code Playgroud)