将指向QML字符串属性的指针传递给C ++

时间:2018-06-14 21:38:42

标签: c++ qt qml

如何将指向字符串属性的指针从QML传递给C ++?

当我试图以明显的方式做到这一点时,我收到了这个错误:

qrc:/NewAccount.qml:236: Error: Unknown method parameter type: QString*

这意味着,在调用new_account.error_string(Q_INVOKABLE)方法时,QML引擎无法将save_account属性转换为C ++

这是我在QML中的代码:

import myproject.aewm.ethkey 1.0
import myproject.aewm.walletaccount 1.0
...
id: new_account
property EthKey key: EthKey{}
property WalletAccount account: WalletAccount{}
property string error_string: ""
....
if (aewm_obj.save_account(key,account,new_account.error_string)) {
    wallet_accounts_tabbar.currentIndex=0
} else {
    console.log("error occurred:"+new_account.error_string)
}

其中aewm_obj是C ++类型(在QML中注册),save_account在C ++中声明为:

Q_INVOKABLE     bool save_account(EthKey *key, WalletAccount *account, QString *err_str);

文档说(QML)string属性是QString对象,并且这些类型是从C ++和QML自动转换的。我在qmlRegisterType()调用后没有任何问题地传递指向我的自定义QObject派生类的指针,那么为什么我不能对字符串做同样的事情呢?

我认为可能不支持字符串指针,我试图添加这一行:

qRegisterMetaType<QString*>("QString*");

但是在这个改变之后,我在C ++端收到的指针是0x0,我得到了一个段错误。

那么,如何将指向QML字符串属性的指针从QML传递给C ++?

或者,你认为我也应该用qmlRegisterType()注册QString类吗?我试了但是我遇到了一些编译问题,所以我认为它不会编译。

最后一个解决方案是创建一个内部带有QString的自定义对象,并从QML向C ++发送指向它的指针。但是,如果QString存在,为什么不找到使用它的方法呢?这将是一种矫枉过正的行为?

非常感谢您的评论。我肯定想使用指针,它比在C ++和QML之间交换数据时处理对象所有权更安全。

2 个答案:

答案 0 :(得分:1)

正如我在评论中所说,QML只传递来自QObject的指针,QString不是QObject

我认为您对该问题的处理方法不正确,您可以在对象中创建一个属性,该属性执行具有错误消息的计算,如下所示。

<强>的main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>

class Foo: public QObject{
    Q_OBJECT
    Q_PROPERTY(QString errorMessage READ errorMessage)
public:
    using QObject::QObject;
    Q_INVOKABLE bool process(int a, int b, int res){
        bool status;
        // some operation
        status = (a+b) == res;
        mErrorMessage = status? "": QString("error message: %1 + %2 is different to %3").arg(a).arg(b).arg(res);
        return status;
    }
    QString errorMessage() const{
        return mErrorMessage;
    }

private:
    QString mErrorMessage;
};

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    qmlRegisterType<Foo>("com.eyllanesc.org", 1, 0, "Foo");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

#include "main.moc"

<强> main.qml

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4

import com.eyllanesc.org 1.0

Window {
    visible: true
    width: 640
    height: 480

    Foo{ id: foo }

    Row{
        SpinBox{ id: a }
        SpinBox{ id: b }
        SpinBox{ id: c }

        Button{
            text: "process"
            onClicked: {
                var message;
                if(foo.process(a.value, b.value, c.value)){
                    message = "correct"
                    console.log("successful")
                }
                else{
                    message = foo.errorMessage
                    console.log("error is "+ message)
                }
                txt.text = message
            }
        }
        Label{ id: txt }
    }
}

答案 1 :(得分:1)

使用Qt,C ++ API和QML API完全不同,实际上是不兼容的层。为了使整个过程工作,有很多来回的数据转换。当谈到像字符串这样的原语时,你并没有真正掌控它。所以只是从脑子里想出来。

如果要访问特定对象的特定属性,则需要传递将作为指针接收的对象和属性名称,然后可以通过QObject通过其名称字符串访问该属性名称s property()setProperty()

但在你的情况下,这完全是多余的,只需传递字符串本身。