user24126140
user24126140

Reputation: 1

Qt6 QAbstractListModel - constructor with two arguments - qml Element is not creatable

I try to use a kind of source code for Qt6, which in principle worked with Qt5: I want to make a graphical output for my system of hardcore particles. In the constructor of the QAbstractListModel I have two arguments: System *system, QObject *parent=0 I think the *system argument is the reason, why in the qml the item Hardcore_Entrymodel{} is not creatable (QQmlApplicationEngine failed to load component).

How can I make my qml File work again?

I ported the model stuff from a sheepflock simulation with qt5 which in principle worked. Now, with the new hardcore model and with qt6 the qml file errors. I did a recherche in the web and got a feeling, it errors because of the two argument constructor.

The Header File of Hardcore_Entrymodel:

class Hardcore_Entrymodel : public QAbstractListModel
{
    Q_OBJECT
public:
    explicit Hardcore_Entrymodel(System*, QObject *parent = 0);
    virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
    QVariant data(const QModelIndex &index, int role) const;
    void populate();

    QHash<int, QByteArray> mPropertyNames;

    enum mParticleProperties{
        type = Qt::UserRole,
        iparticle = Qt::UserRole+1,
        size_semimajoraxis = Qt::UserRole+2,
        size_semiminoraxis = Qt::UserRole+3,
        x_mid_pxl = Qt::UserRole+4,
        y_mid_pxl = Qt::UserRole+5,
        xy_angle_degree = Qt::UserRole+6,
        typecolor = Qt::UserRole+7,
    };

    Q_INVOKABLE void doNewStep();
    Q_INVOKABLE void stepReady();
    Q_INVOKABLE int returnWindowLx();
    Q_INVOKABLE int returnWindowLy();
    Q_INVOKABLE int returnSteptime_ms();

    bool isNewStep();
    void setIsNewStep(bool newS);


protected:
    virtual QHash<int, QByteArray> roleNames() const override;
private:
    System *hardcoresystem;
    int nparticles;
    InitQtView initqtview;
    QList<std::tuple<std::string, int,int,int,int,int, QColor> > mDatas;
    bool newStep;

signals:
    void newStepDoing();
    void newStepReady();

public slots:
    void onNewStepDone();
};

The main function:

#include <QObject>
#include <QGuiApplication>
#include <QQmlApplicationEngine>

#include "Hardcore_InitClass.h"
#include "Hardcore_Entrymodel.h"

int main(int argc, char *argv[])
{
    Hardcore_InitClass initClass(argc, argv);
    System system;
    initClass.return_Hardcoresystem_single(&system);
    system.writeParametersFile();

    QGuiApplication app(argc, argv);

        // register the type DataEntryModel
        // under the url "org.example" in version 1.0
        // under the name "DataEntryModel"
    qmlRegisterType<Hardcore_Entrymodel>("org.hardcoresystem", 1, 0, "Hardcore_Entrymodel");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/qt/qml/Main.qml")));

    return app.exec();
}

And the first part of the qml file:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
//import QtQuick.Layouts 2.2
import QtQml.Models 2.12
import Qt.labs.qmlmodels 1.0

import org.hardcoresystem 1.0

Window {
    id: appwindow
    visible: true
    width: hardcoreentrymodel.returnWindowLx()
    height: hardcoreentrymodel.returnWindowLx()


    Rectangle{
        id: hardcoresystemrectangle
        anchors.left: appwindow.left
        anchors.top: appwindow.top
        width: appwindow.width
        height: appwindow.height
        color: "white"
    }

    Hardcore_Entrymodel{
        id: hardcoreentrymodel
        //onNewPathDoing: console.log("New Path doing ...\n")
        //onNewPathReady: {console.log("New Path ready ...\n")}
        //onDataChanged:  console.log("DataChanged received")
      }

    Timer {
        id: steptimer
        interval: Number(hardcoreentrymodel.returnSteptime_ms())
        //interval: 100
        repeat: true
        running: true
        triggeredOnStart: true
        onTriggered: {hardcoreentrymodel.doNewStep()}
       }

    Item{
        id: partilcesitem
        width: hardcoresystemrectangle.width
        height: hardcoresystemrectangle.height
        anchors.left: hardcoresystemrectangle.left
        anchors.top: hardcoresystemrectangle.top
        Repeater {

[...]

kind regards, Tobias

Upvotes: 0

Views: 298

Answers (2)

Stephen Quan
Stephen Quan

Reputation: 26096

QML requires that components that can be constructed with 0 or 1 explicit parameters. In the latter case, the first argument must be QObject* parameter. The constructor choices you have are:

  1. Hardcore_Entrymodel(QObject *parent = nullptr)
  2. Hardcore_Entrymodel(QObject *parent = nullptr, System* system = nullptr);
  3. Provide two constructors.

Personally, I recommend you go with 1 and remove the System* from your constructor since your solution requires you to instantiate and make System* only available to one of your model instances.

Since your model is creatable, I feel that you need the System* to be available to all your models, so therefore, I feel your System* should be a static member. Doing so, means that it is initializable without an instance of your model.

// Hardcore_Entrymodel.h
class Hardcore_Entrymodel : public QAbstractListModel
{
    Q_OBJECT
public:
    explicit Hardcore_Entrymodel(QObject *parent = nullptr);
public:
    // Static Methods
    static void SetSystem(System* value) { g_hardcoresystem = value; } 
    static System* GetSystem() { return g_hardcoresystem; }

private:
    // Static Member
    static System *g_hardcoresystem;
};

Initialize your static member...

// Harcode_Entrymodel.cpp
System* Hardcore_Entrymodel::g_hardcodesystem = nullptr;

In your main.cpp you can populate your static member without needing to invoke the constructor.

/// main.cpp
int main(int argc, char *argv[])
{
    System system;
    Hardcore_Entrymodel::SetSystem(&system);
    // ...

Upvotes: 0

user24126140
user24126140

Reputation: 1

From Stephen Quans idea, I made hardcoresystem to a static variable for all:

static System *hardcoresystem;

class Hardcore_Entrymodel : public QAbstractListModel
{
    Q_OBJECT
    QML_ELEMENT

public:
[..]

and in main:

int main(int argc, char *argv[]){
Hardcore_InitClass initClass(argc, argv);
System system;
initClass.return_Hardcoresystem_single(&system);
system.writeParametersFile();

hardcoresystem= &system;

QGuiApplication app(argc, argv);

[...]

Now, I think the Qt stuff should work. But, I have still to debug the communication between the qml file and the QAbstractListModel. This will take a bit time. But, thanks until here!

Tobias

Upvotes: 0

Related Questions