Динамически создавайте объект qml из объекта c ++ (используя setContextProperty)

Я пытаюсь создать объект qml динамически в C ++, используя объект класса C ++. Ниже приведен минимальный код для моего подхода. При выполнении этого кода и после щелчка приложение падает (см. Комментарий в main.qml).

Я вставил код ниже и его можно скачать Вот.

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "scene.h"int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;

engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
scene sc(engine);

QQmlContext* context = engine.rootContext();
context->setContextProperty("sc", &sc);

if (engine.rootObjects().isEmpty())
return -1;

return app.exec();
}

scene.h

#ifndef SCENE_H
#define SCENE_H

#include <QObject>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
class scene : public QObject
{
Q_OBJECT
public:
explicit scene(QQmlApplicationEngine& engine, QObject *parent = nullptr);
QQmlApplicationEngine& engine;

public slots:
void create_rect_object();
};

#endif // SCENE_H

scene.cpp

#include "scene.h"
scene::scene(QQmlApplicationEngine &engine, QObject *parent) : engine(this->engine),QObject(parent)
{

}
void scene::create_rect_object()
{
QQmlComponent component(&engine, QUrl::fromLocalFile("myrect.qml"));
QObject *object = component.create();
object->setProperty("width", 200);
object->setProperty("height", 150);
object->setProperty("color", "blue");
}

main.qml

import QtQuick 2.11
import QtQuick.Window 2.11

Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle{
anchors.fill: parent
color: "red"MouseArea{
anchors.fill: parent
onClicked: {
console.log("Before click");
sc.create_rect_object(); // application is crashing here
console.log("after click");
}
}
}
}

myrect.qml

import QtQuick 2.0

Rectangle {
id:id_rec
width: 100
height: 100
color: "green"x:0
y:0
}

Обновить

Создаваемый объект не является дочерним элементом корня главного окна, но является дочерним элементом одного из элементов в цепочке дочерних элементов корневого главного окна. Псевдоструктура выглядит следующим образом.

main.qml

Window {

customitem1{
id:id_ci1

}
customitem2{
id:id_ci1
}
}

customitem1.qml

Item {

customitem3{
id:id_ci3

}
customitem3{
id:id_ci4
}
}

0

Решение

[ОБНОВЛЕНО]

У вас есть две ошибки при сбое и одна не показывает прямоугольники

1.Ваш scene«s Список инициализатора члена конструктора это ложь, которая вызывает сбой приложения

(СОВЕТ: используйте разные имена для членов класса, добавив к ним префикс m_ например: m_engine за ЧИТАЕМОСТЬ и не получить смущенный)

//Correct WAY
class Something
{
private:
int m_value1;
double m_value2;
char m_value3;

public:
//#################  YOUR CASE  ###############################
Something(int number) : m_value1(number), m_value2(2.2), m_value3('c') // directly initialize our member variables
{
// No need for assignment here
}
//#############################################################
Something() : m_value1(1), m_value2(2.2), m_value3('c') // directly initialize our member variables
{
// No need for assignment here
}
void print()
{
std::cout << "Something(" << m_value1 << ", " << m_value2 << ", " << m_value3 << ")\n";
}
}

и так должно быть:

scene::scene(QQmlApplicationEngine &engine, QObject *parent) : engine(engine),QObject(parent)

вместо

scene::scene(QQmlApplicationEngine &engine, QObject *parent) : engine(this->engine),QObject(parent)

2. url из myrect.qml который вы получаете из локального файла, который не найден в время выполнения вызвало аварийное завершение работы приложения, и одно из средств защиты — загрузить его из qrc файл

 QQmlComponent component(&engine, QUrl("qrc:/myrect.qml"));

3. И вы заметите, что после нажатия у вас нет прямоугольников, потому что создаваемые прямоугольники не имеют родителя и, изменяя ваш create_rect_object()(В этом примере родитель является невидимым корнем нашего окна contentItem) вы получите несколько прямоугольников 🙂

//A QQuickWindow always has a single invisible root item containing all of its content.
//To add items to this window, reparent the items to the contentItem or to an existing item in the scene.
//http://doc.qt.io/qt-5/qquickwindow.html#contentItem-propvoid scene::create_rect_object()
{
QQmlComponent component(&engine, QUrl("qrc:/myrect.qml"));

QObject *object = component.create();
QQuickItem *item = qobject_cast<QQuickItem*>(object);
// Set the parent of our created qml rect
item->setParentItem((QQuickItem*)((QQuickWindow *) engine.rootObjects()[0])->contentItem());
//Set some random position and color
item->setProperty("color", QColor::fromRgb(QRandomGenerator::global()->generate()));
item->setX(20+qFloor(QRandomGenerator::global()->generateDouble()*20));
item->setY(20+qFloor(QRandomGenerator::global()->generateDouble()*20));

}

Поиск объектов QML из C ++

Для поиска объектов и их использования в качестве parentItem, вы должны установить objectName вашего объекта qml

Rectangle {
...
objectName : "rect_1"...
}

и в C ++

QObject* obj = dynamic_cast<QObject*>(engine.rootObjects()[0]).findChild("rect_1");
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]