从没有ObjectName的C ++访问QML子组件?

时间:2018-04-06 08:21:10

标签: qt qml qtquick2

我正在用QML创建一个绘图组件。我的QML组件的结构如下所示:

Rectangle {
  id: canvas
  objectName: "myPlot"
  Rectangle {
    id: plot
    PlotArea {
      id: pa
    } // this is my c++ QQuickItem
    MouseArea {} // for handling interaction with the plot, like zooming
    XAxis{}
    YAXis{}
  }
}

这里PlotArea是我的c ++类。我需要与C ++中的这个QML组件进行交互,更准确地说,我需要调用PlotArea的成员函数来向绘图添加数据。通常的方法是使用findChild<QObject*>("objectName"),但由于组件将被重用,我无法提供PlotArea和对象名称。

如果我有指向PlotArea的指针,如何访问"myPlot"?我试过了

QObject *plot = rootObjects.value(0)->findChild<QObject*>("plotObject");
PlotArea * myplot = (plot->findChild<PlotArea*>("pa"));

但这不起作用。但是,如果我这样做,那么上述方法是有效的

PlotArea {
  id: pa
  objectName: "pa"
} // this is my c++ QQuickItem

但是我想知道这是否安全,因为我的应用程序中会有服务PlotAreas,并且所有这些都有#34; pa&#34;。

2 个答案:

答案 0 :(得分:5)

除非您正在编写单元测试,否则不应该使用C ++与QML交互。有关说明,请参阅this documentation

更好的方法是将C ++类型公开给QML。

的Singleton

例如,您可以注册将绘图数据添加为singleton的C ++类:

qmlRegisterSingletonType<PlotDataAdder>("App", 1, 0, "PlotDataAdder", plotDataAdderCreationFunction);

然后你可以用QML做到这一点:

import App 1.0

PlotArea {
    id: plotArea
    Component.onCompleted: PlotDataAdder.addData(plotArea)
}

这是一种必要的方法。

命名类型

如果在您的情况下可行,您可以使用qmlRegisterType()以声明方式执行此操作:

qmlRegisterType<PlotDataSource>("App", 1, 0, "PlotDataSource");

然后,在QML中:

import App 1.0

Window {
    PlotDataSource {
        id: plotDataSource
    }

    PlotArea {
        id: plotArea
        plotData: plotDataSource
    }
}

你说情节数据是由硬件动态生成的,所以这种方法在这种情况下会起作用,而使用单例的第一种方法会更难。

上下文属性

或者,如果您无法按需创建C ++类(例如,如果它来自第三方库),请使用setContextProperty()

engine.rootContext()->setContextProperty("plotDataSource", plotDataSource);

然后,在QML中:

import App 1.0

Window {
    PlotArea {
        id: plotArea
        plotData: plotDataSource
    }
}

答案 1 :(得分:1)

下面的代码只是解决问题的一种方法,但不是正确的答案,因为它会弄乱QML对象的所有权。 PlotAreaQML引擎生成,但在C ++端使用。要正确解决问题,建议重新设计PlotArea

C ++:

QObject* test = engine.rootObjects()[0]->findChild<QObject*>("test");
PlotArea* plotArea = test->property("plotArea").value<PlotArea*>();

QML:

Item{
    objectName: "test"
    property var plotArea : plotArea
    Item{
        PlotArea{
            id: plotArea
        }
    }
}