如何在QML Javascript中创建和使用C ++对象

时间:2014-05-28 23:47:12

标签: javascript qml qt5 qt-quick qtquick2

我的应用程序同时使用c ++和QML。

我已经在C ++部分定义了几个对象来访问SQL等。

看起来像:

class MyObject : public QObject
{
    Q_OBJECT
public:
    MyObject(QObject *parent = 0);
    Q_INVOKABLE void someFunction(const QString &query);
};

qmlRegisterType<MyObject>("xxx.xxx", 1, 0, "MyObject");

理想情况下,我只需要在JML中使用这些对象,而不是在QML中。

我尝试了很多例子并阅读了所有文档,但仍无法解决我的问题。

所以我的问题:

  • 如何在Javascript中实例化C ++中定义的对象?我试过var obj = Qt.createComponent("MyObject");,但似乎不行。是否可以用正常的JS样式定义新对象 - var obj = new MyObject;
  • 如何在javascript中访问此创建的对象?我尝试了obj.someFunction(&#34; xxx&#34;)但出现了一些错误 - TypeError: Property 'someFunction' of object QQmlComponent(0x3605f5c0) is not a function.我在这里做错了什么?我的对象派生自QObject,而不是来自QQmlComponent。

4 个答案:

答案 0 :(得分:4)

您的对象不是Component,但您可以改为使用Qt.createQmlObject

答案 1 :(得分:2)

文档很清楚,但混淆看起来像是在QML方面。这应该让你开始:

//C++
class MyObject : public QObject
{
    Q_OBJECT
public:
    MyObject(QObject *parent = 0);
    Q_INVOKABLE void someFunction(const QString &query) { qDebug() << query;}
};
....
qmlRegisterType<MyObject>("foo.bar", 1, 0, "MyObject");

QML如下:

import foo.bar 1.0 //This is your register type
Item {
  MyObject { //here's the instance, remember it is declarative
    id: myObject;
  }
  MyObject {
    id: myObjectInstance2
  }
  Button {
    onClicked: {
      myObject.someFunction("doSomething"); //here is using a reference
      myObjectInstance2.someFunction("doSomethingElse");
    }
  }
}

点击后你应该看到输出中的字符串(我没有编译或测试它)。请务必在主类中注册类型。

如果您在移动设备上使用SQL,则应该检查本地存储对象。这是一个非常简单的回调API,适用于SQLite。我将它用于桌面应用程序,并没有太多麻烦。返回列表有点烦人,所以只需坚持使用简单类型即可轻松实现JavaScript集成。

我希望有所帮助。我非常喜欢在QML中工作,一旦你学会了它就会非常有趣(足够熟练工作1-2周)。

答案 2 :(得分:2)

您可以使用

QQmlApplicationEngine engine;
engine.globalObject().setProperty("CppCreator", engine.newQObject(&CppCreator::GetInstance()));

CppCreator是一个用于创建其他c ++对象的QObject

Q_INVOKABLE QObject* Create(const QString& type_name);

然后你可以在qml js中创建c ++对象,比如

var test = CppCreator.Create("Your Type");

这不完美,但满足了我的要求。希望它可以帮到你。

答案 3 :(得分:0)

这是一个有想象的// Factory class class Creator : public QObject { Q_OBJECT public: Q_INVOKABLE QObject* createObject(const QString& typeName, const QVariantMap& arguments); }; QObject* Creator::createObject(const QString& typeName, const QVariantMap& arguments) { if (typeName == "TextFile") { QString filePath = arguments.value("filePath").toString(); TextFile::OpenMode openMode = qvariant_cast<TextFile::OpenMode>(arguments.value("openMode", TextFile::ReadWrite)); QString codec = arguments.value("codec", "UTF-8").toString(); return new TextFile(qmlEngine(this), filePath, openMode, codec); } Q_ASSERT(false); return nullptr; } 类的例子。首先,我们需要一个已建议的工厂类:

TextFile

注意:这个类比必要的要复杂一些。它应该创建多种类型。现在我们已经有了工厂类,我们需要告诉QML / QJSEngine在调用 QJSValue creator = engine.newQObject(new Creator()); engine.globalObject().setProperty("_creator", creator); engine.evaluate("function TextFile(path, mode) { return _creator.createObject(\"TextFile\", { filePath: path, openMode: mode }); }"); 的new运算符时该怎么做。

TextFile

现在我们可以根据需要实现我们的var myFile = new TextFile("/path/to/file", TextFile.ReadWrite); ,即使是参数:

<aside id="appNav" class="fixed-top">
<div id="appNavTop" class="appHide">
<div class="container">
<div class="row">
<div class="col-12">
<span>appNavTop</span>
</div>
</div>
</div>
</div>
[...]
</aside>

.appHide {
height: 0 !important;
overflow: hidden
}
#appNavTop {
-webkit-transition-property: height;
transition-property: height;
height: 40px
}

$(window).on('scroll', function () {
if ($(document).scrollTop() > 0) {
$('#appNavTop').removeAttr('class');
} else {
$('#appNavTop').addClass('appHide');
}
});

致信this answer的作者。