4

I tried to operate a part of a qt project in Qt\Examples\Qt-5.9\quick\views, I am new to qml and I am trying to open each time a different QDialog window depending on qml pathview component that has been clicked. First of all, I started with creating a class (interfacageQML) which will serve to interface the qml Mainform and the QDialog (qtinterface), the necessary files are included among which interfacageqml.h.

here is the main.cpp :

#include "interfacageqml.h"                                               

int main(int argc, char *argv[]) 
{                                                             
    QGuiApplication app(argc, argv);             
    qmlRegisterType<interfacageQML>("Interfacage", 1, 0,"Component:MouseArea");

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

   return app.exec();                                                          
}

And here's interfacageqml.h :

#ifndef INTERFACAGEQML_H
#define INTERFACAGEQML_H

#include <QObject>
#include "qtinterface.h"

class interfacageQML : public QObject
{
Q_OBJECT

public:
interfacageQML(QObject *parent);
~interfacageQML();


Q_INVOKABLE void mouseClick();

signals:
    void clicked();

};

#endif // INTERFACAGEQML_H

interfacageqml.cpp :

#include "interfacageqml.h"
#include <QDebug>
#include <QApplication>

interfacageQML::interfacageQML(QObject *parent)
    : QObject(parent)
{

}

interfacageQML::~interfacageQML()
{

}

void interfacageQML::mouseClick()
{
    qDebug() << "qmlinterface::mouseClick()";
    emit clicked();
}

My project is organised this way :

enter image description here

the qmlinterface.qrc file contains these paths:

enter image description here

main.qml :

import QtQuick 2.6
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    MainForm{
        anchors.fill: parent
    }
}

MainForm.qml :

import QtQuick 2.6
import QtQuick.Controls 2.0 as QQC2
import Interfacage 1.0


Rectangle {
    width: 800
    height: 800
    color: "white"

    ListModel {
        id: appModel
        ListElement {
            name: "Contacts"
            icon: "pics/Resources/AddressBook_48.png"
        }
        ListElement {
            name: "Music"
            icon: "pics/Resources/AudioPlayer_48.png"
        }
        ListElement {
            name: "Movies"
            icon: "pics/Resources/VideoPlayer_48.png"
        }
        ListElement {
            name: "Camera"
            icon: "pics/Resources/Camera_48.png"
        }
        ListElement {
            name: "Calendar"
            icon: "pics/Resources/DateBook_48.png"
        }
        ListElement {
            name: "Todo List"
            icon: "pics/Resources/TodoList_48.png"
        }
    }

    Component {
        id: appDelegate
        Item {
            width: 100
            height: 100
            scale: PathView.iconScale

            Image {
                id: myIcon
                y: 20
                anchors.horizontalCenter: parent.horizontalCenter
                source: icon
            }
            Text {
                anchors {
                    top: myIcon.bottom
                    horizontalCenter: parent.horizontalCenter
                }
                text: name
            }

            MouseArea {
                anchors.fill: parent
                onClicked: {
                    view.currentIndex = index
                    Interfacage.mouseClick
                }
            }
        }
    }

    Component {
        id: appHighlight
        Rectangle {
            width: 100
            height: 80
            color: "lightsteelblue"
        }
    }

    PathView {
        id: view
        anchors.fill: parent
        highlight: appHighlight
        preferredHighlightBegin: 0.5
        preferredHighlightEnd: 0.5
        focus: true
        model: appModel
        delegate: appDelegate
        path: Path {
            startX: 50
            startY: 80
            PathAttribute {
                name: "iconScale"
                value: 2.0
            }
            PathQuad {
                x: 250
                y: 200
                controlX: 50
                controlY: 200
            }
            PathAttribute {
                name: "iconScale"
                value: 2.0
            }
            PathQuad {
                x: 600
                y: 50
                controlX: 400
                controlY: 200
            }
            PathAttribute {
                name: "iconScale"
                value: 2.0
            }
        }
    }
}

When I run this project, i got an error :

error:C2280

However, when I comment this line : qmlRegisterType<interfacageQML>("Interfacage", 1, 0, "Component:MouseArea"); the project runs and I can navigate between the pathview components in the MainForm.

Khaled
  • 81
  • 1
  • 14
  • Why have you deleted the prior question? I was just about to answer it, when it got deleted. Nevermind. My answer was almost the same as Eyllanescs. Maybe less extensive. – derM - not here for BOT dreams Dec 08 '17 at 17:06
  • I thaught I had an error, the thing is each time I modify the qml files I need to open qmlinterface.qrc and click the save button. – Khaled Dec 08 '17 at 17:22

1 Answers1

4

When you use qmlRegisterType you are registering a new data type in QML, it is not an object, in that case the name "Component: MouseArea" is not suitable.

qmlRegisterType<interfacageQML>("Interfacage", 1, 0, "InterfacageQML");

Another error is that you must pass a parent by default, in this case 0 or nullptr since the items may not have parents.

class interfacageQML : public QObject
{
    Q_OBJECT
public:
    explicit interfacageQML(QObject *parent = nullptr);
    [...]

As I said in the first lines, this is a new type, it is not an object so you must create it.

import QtQuick 2.6
import QtQuick.Controls 2.0 as QQC2
import Interfacage 1.0

Rectangle {
    width: 800
    height: 800
    color: "white"

    InterfacageQML{
        id: myitem
    }
    [...]

And in the end if you want to use it you must call the function through the item.

MouseArea {
    anchors.fill: parent
    onClicked: {
        view.currentIndex = index
        myitem.mouseClick()
    }
}

Since you want to connect your QDialog with the QML through that class, you can not do it since they will be different objects, one solution for this is to use a singleton, for this you must do the following:

interfacageqml.h

#ifndef INTERFACAGEQML_H
#define INTERFACAGEQML_H

#include <QObject>
#include <QQmlEngine>    

class interfacageQML : public QObject
{
    Q_OBJECT
    static interfacageQML* instance;
    explicit interfacageQML(QObject *parent = nullptr);
public:
    static interfacageQML *getInstance();
    ~interfacageQML();
    Q_INVOKABLE void mouseClick();

signals:
    void clicked();
};
#endif // INTERFACAGEQML_H

interfacageqml.cpp

#include "interfacageqml.h"
#include <QDebug>

interfacageQML* interfacageQML::instance = 0;

interfacageQML *interfacageQML::getInstance()
{
    if (instance == 0)
        instance = new interfacageQML;
    return instance;
}

interfacageQML::interfacageQML(QObject *parent) : QObject(parent)
{
}

interfacageQML::~interfacageQML()
{
}

void interfacageQML::mouseClick()
{
    qDebug() << "qmlinterface::mouseClick()";
    emit clicked();
}

main.cpp

#include "interfacageqml.h"

#include <QGuiApplication>
#include <QQmlApplicationEngine>

static QObject *singletonTypeProvider(QQmlEngine *, QJSEngine *)
{

    return interfacageQML::getInstance();
}


int main(int argc, char *argv[])
{
    qmlRegisterSingletonType<interfacageQML>("Interfacage", 1, 0, "InterfacageQML", singletonTypeProvider);

    // test
    interfacageQML *obj = qobject_cast<interfacageQML*>(interfacageQML::getInstance());
    QObject::connect(obj, &interfacageQML::clicked,[]{
        qDebug()<<"clicked";
    });

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

As it is a singleton it is not necessary to create an item, you can do it directly:

import Interfacage 1.0
[...]
MouseArea {
    anchors.fill: parent
    onClicked: {
        view.currentIndex = index
        InterfacageQML.mouseClick()
    }
}

This last example can be found in the following link.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Yes I have, now the qml interface opens – Khaled Dec 08 '17 at 17:05
  • 1
    @Khaled If it worked, do not forget to mark my answer as correct, if you do not know how to do it, check the following link: [tour] – eyllanesc Dec 08 '17 at 17:06
  • However, I can not see the qDebug messages when I click on an item. – Khaled Dec 08 '17 at 17:08
  • How strange, click on the names. – eyllanesc Dec 08 '17 at 17:09
  • Maybe the print mode is not enabled in Visual Studio, I execute it correctly in QtCreator, try it directly with your QDialog or execute it through QtCreator. – eyllanesc Dec 08 '17 at 17:11
  • Ow It's normal that it doesn't work, I forgot that I deleted "import Interfacage 1.0" and the Object that I added because it didn't recognize the path. – Khaled Dec 08 '17 at 17:16
  • @Khaled Do not forget to mark my answer as correct, for that you must press the check that is on the left side of my question. – eyllanesc Dec 08 '17 at 17:19
  • Thank you for the solution @Eyllanesc, but I don't understand why it's not recognizing the path.. – Khaled Dec 08 '17 at 17:24
  • @Khaled Check if the names are correct, QML differentiates between uppercase and lowercase, in addition to the following line `qmlRegisterSingletonType ("Interfacage", 1, 0, your_item, singletonTypeProvider);` your_item should start with capital letters. the name `Component:MouseArea` is invalid. – eyllanesc Dec 08 '17 at 17:27
  • It's recognizing it now when I added the main.qml and the MainForm.qml into the Resource Files Directory, but the click event is not detected..Even when I add a messageBox and execute it. – Khaled Dec 08 '17 at 17:47
  • According to the image that you showed the .qml were in your .qrc, so if you have modified that part, it gives me to think that maybe you have modified other things, I recommend you to continue reviewing since that depends on your configuration, it is impossible help you if it is like that. – eyllanesc Dec 08 '17 at 17:53
  • The error is that, qrc:/MainForm.qml:38 Element is not creatable. which is **InterfacageQML { id: myitem }** – Khaled Dec 08 '17 at 18:15
  • You do not have to create it, delete that part, if you have read my answer the solution is to use a singleton, and a singleton you should not create it, just use it. Check my code and you will understand. – eyllanesc Dec 08 '17 at 18:17
  • It worked finally, thank you really. I really need to understand this singleton object and it's capabilities. – Khaled Dec 08 '17 at 18:25
  • I was so eager to make it work, I didn't pay attention to the last part of your answer. – Khaled Dec 08 '17 at 18:27
  • You have to read the answers, for something we spend time justifying them, that's the interesting part. – eyllanesc Dec 08 '17 at 18:29
  • I guess when I read it I thought it was an improvement or a better way to do it.. Anyway, thank you. – Khaled Dec 08 '17 at 18:32