简体   繁体   English

从C ++对象动态创建qml对象(通过使用setContextProperty)

[英]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));

}

Finding QML Objects from C++ 从C ++查找QML对象

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM