如何在 C++ 端获取有效的 QQuickItem 实例

2022-01-19 00:00:00 qt qml c++ qquickitem qqmlcomponent

好的.我已经搜索了很多,但还没有一个好的解决方案.我是 Qt 的新手.我有一个像这样的 QQuickItem 类,

Alright. I have searched a lot but haven't got a good solution yet. I am new to Qt. I have a class which is a QQuickItem like so,

class MyQuickItemClass : public QQuickItem
{
    Q_OBJECT
    SetInfo(SomeCppClass object)
};

我在我的 main.cpp 中做了一个 qmlRegisterType 来像这样在 qml 端注册它,

I do a qmlRegisterType in my main.cpp to register it on the qml side like this,

qmlRegisterType

MyQuickItemClass >("MyQ??uickItemClass", 1, 0, "MyQuickItemClass");

qmlRegisterType< MyQuickItemClass >("MyQuickItemClass", 1, 0, "MyQuickItemClass");

到这里为止一切都很好.但是 -> 我想设置一个对象实例 &MyQuickItemClass 中的一些属性,其中还有一些 C++ 逻辑 &然后将 MyQuickItemClass 对象传递给 qml.或者,从 Qml 获取 MyQuickItemClass 的有效实例.如何在 main.cpp 的 C++ 端从 QML 获取 vlid 实例 MyQuickItemClass 对象实例?

All fine till here. But -> I want to set an object instance & some properties in MyQuickItemClass which some C++ logic in it as well & then pass the MyQuickItemClass object to qml. Or, get a valid instance of MyQuickItemClass from Qml. How can I get a vlid instance MyQuickItemClass object instance from QML on C++ side in main.cpp ?

我尝试从此处链接进行以下学习.但是这种技术会创建两个独立的 MyQuickItemClass 对象.QML 中的一个,&c++ 方面的一个.因此对我不起作用.

I tried doing the following learning from the link here. But this technique creates two separate objects of MyQuickItemClass. One from QML, & one from c++ side. Hence does not work for me.

以下是我经过大量搜索后尝试执行此操作的方式.

Following is how I am trying to do this after lot of searching.

int main(int argc, char *argv[]) 
{
  qmlRegisterType< MyQuickItemClass >("MyQuickItemClass", 1, 0, "MyQuickItemClass");
  QQmlApplicationEngine engine;
  SomeCppClass someCppClassObject;
  someCppClassObject.updateSomething();

  MyQuickItemClass myquickItemObject;
  myquickItemObject.SetInfo(someCppClassObject);
  engine.rootContext()->setContextProperty("myquickItemObject", &myquickItemObject);

  engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
  return app.exec();
}

但是,执行上述操作会使 MyQuickItemClass 的构造函数被调用两次.当我创建一个对象时,一次来自 cpp 端,一次来自 qml 端.通过在 MyQuickItemClass 的构造函数中放置一个断点来验证这一点.结果,当程序运行时,我在 MyQuickItemClass 中设置的 someCppClassObject 为空.因为 qml 已经对 MyQuickItemClass 进行了最终调用来实例化,因此忽略了我在 main.cpp 中创建的 MyQuickItemClass 对象.

But, doing the above gets the constructor of MyQuickItemClass called twice. Once from cpp side when I created an object, and once from qml side. Verified this by placing a breakpoint in the constructor of MyQuickItemClass as well. As a result, someCppClassObject that I had set is null inside MyQuickItemClass when program runs. Because qml has made the final call to MyQuickItemClass to instantiate, thusly ignoring the MyQuickItemClass object that I created in main.cpp.

这是我的 MyQuickItemClassqml 代码:

Here is my qml code for MyQuickItemClass:

import QtQuick 2.5
import MyQuickItemClass 1.0

ParentContainerItem {
  id: parentItem
  color: "black"

  MyQuickItemClass {
      id: myQuickItemID
      visible: true
      objectName: "myQuickItem"

      property bool someProperty1: false
      property bool someProperty2: true

      anchors.top: parent.top
      anchors.horizontalCenter: parent.horizontalCenter
  }

  //Other qml components
}

这是需要将其对象设置为MyQuickItemClass的C++类.

And this is the C++ class whose object needs to be set into MyQuickItemClass.

SomeCppClass {
  //Pure C++ class. No Qt
}

请注意,我需要保留从 QQuickItem 派生的 MyQuickItemClass.请建议...

Please note that I need to keep MyQuickItemClass derived from QQuickItem. Please suggest...

推荐答案

一般来说,避免从外部访问 QML 实例化对象 是个好主意,因为大多数访问方法都会产生从 C++ 到QML,限制了 QML 树的完成方式.

Generally it is a good idea to avoid accessing QML instantiated objects from outside as most of the access methods generated a dependency from C++ toward QML, restricting the way the QML tree is done.

例如要求某些对象在某个时间点存在,具有特定的 objectName 值等.

E.g. requiring certain objects to exist at certain point in times, having specific objectName values, etc.

最好通过在暴露的 C++ 对象/API 上调用方法从 QML 端注册"对象,或者让 QML 在其自己的 C++ 代码中实例化对象注册自己.

It is better to either "register" the object from QML side by calling a method on an exposed C++ object/API or to make the QML instantiate object register itself from within its own C++ code.

后者显然本质上是自动的,即这样一个类的每个实例都会这样做,而前者则让 QML 代码自行决定它想知道哪个已创建的实例.

The latter is obviously inherently automatic, i.e. each instance of such a class would do that, while the former puts it at the discretion of the QML code which of the created instances it wants to make known.

相关文章