[英]Create qml object dynamically from c++ object (by using setContextProperty)
I am trying to create a qml object dynamically in c++ using the object of c++ class. 我正在尝试使用c ++类的对象在c ++中动态创建一个qml对象。 Below is the minimal code for my approach.
下面是我的方法的最小代码。 Upon execution of this code and after clicking, the application is crashing(see the comment in main.qml).
执行此代码后,单击后,应用程序崩溃了(请参阅main.qml中的注释)。
I have pasted the code below and It can be downloaded here . 我已经粘贴了下面的代码,可以在这里下载。
main.cpp 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 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 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 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 myrect.qml
import QtQuick 2.0
Rectangle {
id:id_rec
width: 100
height: 100
color: "green"
x:0
y:0
}
Update 更新
The object to be created is not the child of the root of main window but child of one of the item inside the chain of children items of root of mainwindow. 要创建的对象不是主窗口根目录的子项,而是主窗口根目录的子项链中的一项的子项。 The pseudo structure looks like below.
伪结构如下所示。
main.qml main.qml
Window {
customitem1{
id:id_ci1
}
customitem2{
id:id_ci1
}
}
customitem1.qml customitem1.qml
Item {
customitem3{
id:id_ci3
}
customitem3{
id:id_ci4
}
}
[ UPDATED ] [ 更新 ]
You have two errors for crashing and one for not showing rectangles 您有两个崩溃的错误和一个不显示矩形的错误
1.Your scene
's Constructor member initializer list is falsy which causes the app crash 1.您的
scene
的构造函数成员初始化器列表虚假,导致应用崩溃
( TIP : use different naming for members of the class by prefixing them with m_
eg: m_engine
for READABILITY and not get confused ) ( 提示:通过为类成员添加
m_
前缀为类的成员使用不同的命名,例如: m_engine
表示READABILITY而不引起混淆 )
//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";
}
}
and it should be like this : 它应该是这样的:
scene::scene(QQmlApplicationEngine &engine, QObject *parent) : engine(engine),QObject(parent)
instead of 代替
scene::scene(QQmlApplicationEngine &engine, QObject *parent) : engine(this->engine),QObject(parent)
2.The url
of myrect.qml
which you get from local file that isn't found at runtime caused the app crash aslo and the one of remedies is to load it from your qrc
file 2.从运行时 未找到的本地文件中获取的
myrect.qml
url
导致应用程序崩溃,也补救措施之一是从qrc
文件中加载
QQmlComponent component(&engine, QUrl("qrc:/myrect.qml"));
3.And you'll notice after clicking you got no rectangles that's because the rectangles getting created doesn't have a parent and by changing your create_rect_object()
(In this example the parent is the invisible root of our window contentItem
) you'll get some rectangles :) 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-prop
void 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));
}
For finding objects and using them as parentItem
, you have to set the objectName
of your qml object 为了找到对象,并使用它们作为
parentItem
,你必须设置objectName
的QML对象
Rectangle {
...
objectName : "rect_1"
...
}
and in C++ 和在C ++中
QObject* obj = dynamic_cast<QObject*>(engine.rootObjects()[0]).findChild("rect_1");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.