findChild() does not find objectName() of LineSeries from c++ side
-
Hi,
I created this qml component:MyChartView.qml import QtQuick 2.12 import QtCharts 2.13 Item{ id: root objectName:"root" width: 600 height: 440 ChartView{ id:chartView objectName: "chartView" anchors.fill: parent ValuesAxis{ id:xAxis min: 0 max: 10 } ValuesAxis{ id:yAxis min: 0 max: 10 } LineSeries{ id:lineSeries objectName: "lineSeries" name: "Linea 1" axisX: xAxis axisY: yAxis } } }
in main.cpp I want to access lineSeries through lineSeriesQobject pointer, but it doesn't find objectName() of lineSeries. Below the code of main.cpp.
main.cpp #include <QApplication> #include <QObject> #include <QQuickView> #include <QQmlProperty> #include <QQuickItem> int main(int argc, char *argv[]) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif QApplication app(argc, argv); QQuickView view; view.setSource(QUrl::fromLocalFile(":/MyChartView.qml")); QQuickItem *rootObject=view.rootObject(); if(rootObject){ qDebug()<<rootObject->objectName(); QObject *chartViewObject=rootObject->findChild<QObject*>("chartView"); if(chartViewObject){ qDebug()<<chartViewObject->objectName(); QObject* lineSeriesObject=chartViewObject->findChild<QObject*>("lineSeries"); if(lineSeriesObject){ qDebug()<<lineSeriesObject->objectName(); } } } view.show(); return app.exec(); }
lineSeriesObject pointer return nullptr, what am I doing wrong?
-
@sierdzio Thanks for the quick reply.
Below I update the code as you suggested, but the problem remained the same findChild() still can't find objectName() of lineSeries.main.cpp #include <QApplication> #include <QObject> #include <QQuickView> #include <QQmlProperty> #include <QQuickItem> int main(int argc, char *argv[]) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif QApplication app(argc, argv); QQuickView view; view.setSource(QUrl::fromLocalFile(":/MyChartView.qml")); QQuickItem *rootObject=view.rootObject(); if(rootObject){ qDebug()<<rootObject->objectName(); QObject *lineSeriesObject=rootObject->findChild<QObject*>("lineSeries",Qt::FindChildOption::FindChildrenRecursively); if(lineSeriesObject){ qDebug()<<lineSeriesObject->objectName(); } } view.show(); return app.exec(); }
-
Hello, I found the solution to be able to manipulate the LineSeries from the C++ side in QML. I needed this approach because I want to populate the LineSeries from C++ rather than from QML. I have to work with a large number of points, and populating the LineSeries from QML was proving to be too slow. The chart will display 100 randomly generated points as well. Below you will find the main.cpp, main.qml, and MyChartView.qml files.
main.cpp #include <QApplication> #include <QQmlApplicationEngine> #include <QQmlComponent> #include<QQmlEngine> #include <QAbstractSeries> #include <QLineSeries> #include <QRandomGenerator> int main(int argc, char *argv[]) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif QApplication app(argc, argv); QQmlApplicationEngine engine; const QUrl url(QStringLiteral("qrc:/main.qml")); QQmlComponent component(&engine, url); QObject *rootObject = component.create(); if (rootObject) { QObject *chartViewObject = rootObject->findChild<QObject *>("chartView"); if (chartViewObject) { QAbstractSeries *series = nullptr; QMetaObject::invokeMethod(chartViewObject, "series", Q_RETURN_ARG(QAbstractSeries *, series), Q_ARG(int, 0)); if (series) { QLineSeries *qSeries = qobject_cast<QLineSeries *>(series); QList<QPointF> pointFList; QPointF pointF; series->setProperty("name", "Line 1"); series->setProperty("color", "#FF8000"); for (int i = 0; i < 100; i++) { pointF.setX(i); qint32 randomNumber = QRandomGenerator::global()->bounded(101); pointF.setY(randomNumber); pointFList.push_back(pointF); } qSeries->replace(pointFList); } } } return app.exec(); }
main.qml import QtQuick 2.12 import QtQuick.Window 2.12 Window { id: window width: 640 height: 480 visible: true title: qsTr("Chart") MyChartView{ id:myChartView anchors.centerIn: parent } }
MyChartView.qml import QtQuick 2.12 import QtCharts 2.13 Item { id:root objectName: "root" width: 600 height: 440 ChartView{ id:chartView objectName: "chartView" anchors.fill: parent ValuesAxis{ id:xAxis min: 0 max: 100 } ValuesAxis{ id:yAxis min: 0 max: 100 } LineSeries{ id:lineSeries objectName: "lineSeries" axisX: xAxis axisY:yAxis } } }
-
-
I rewrote the code using VXYModelMapper. It actually results in a more elegant solution and as the Qt documentation points out we keep the C++ side separate from the QML side.
main.cpp
#include <QApplication> #include <QQmlApplicationEngine> #include <QStandardItemModel> #include <QStandardItem> #include <QRandomGenerator> #include <QQmlContext> int main(int argc, char *argv[]) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif QApplication app(argc, argv); //we create a QStandardItemModel object composed of 100 rows and 3 columns QStandardItemModel lineModel(100, 3); for (int row = 0; row < lineModel.rowCount(); row++) { QStandardItem *item1 = new QStandardItem(QString::number(row)); QStandardItem *item2 = new QStandardItem(QString::number(row)); qint32 randomNumber = QRandomGenerator::global()->bounded(101); QStandardItem *item3 = new QStandardItem(QString::number(randomNumber)); //now I assign the items to lineModel lineModel.setItem(row,0,item1); lineModel.setItem(row,1,item2); lineModel.setItem(row,2,item3); } QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("lineModel",&lineModel); const QUrl url(QStringLiteral("qrc:/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
main.qml
import QtQuick 2.12 import QtQuick.Window 2.12 import QtCharts 2.3 Window { width: 640 height: 480 visible: true title: qsTr("Hello World") ChartView { anchors.fill: parent id: chart antialiasing: true ValuesAxis{ id: axisX min: 0 max: 100 } ValuesAxis{ id: axisY min: 0 max: 100 } LineSeries{ id: line name: "Line 1" axisX: axisX axisY: axisY } VXYModelMapper { id: modelMapper model: lineModel series: line firstRow: 0 xColumn: 1 yColumn: 2 } } }