0
votes

I am trying to send a list from QML to c++. I've tried with a string and an integer with success but when I try with a QVariant I get the error:

QObject::connect: No such slot MyClass::cppSlot(QVariant) in ../test_2206/main.cpp:31

My main.qml

import QtQuick 2.4
import QtQuick.Layouts 1.1
import Material.ListItems 0.1 as ListItem
import Material.Extras 0.1
import QtQuick.Controls 1.3 as QuickControls
import QtQuick.Controls 1.4
import Material 0.2


Window {
    visible: true
    property var listCloud: ["nuage1", "nuage2", "nuage3", "nuage4"]
        id: item
        width: 100; height: 100

        signal qmlSignal(variant msg)

       /* MouseArea {
            anchors.fill: parent
            onClicked: item.qmlSignal("Hello from QML")
        }*/
    Rectangle{
        id:sousRect
        color:"red"
        width:100; height:100
            Button{
                id:buttonTest
                onClicked: {
                     item.qmlSignal(listCloud)
                }
            }
    }

}

My main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlProperty>
#include <QQmlComponent>
#include <QDebug>
#include "myclass.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);   
    QQmlApplicationEngine engine;

    QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/main.qml")));
    QObject *object = component.create();

        MyClass myClass;
        QObject::connect(object, SIGNAL(qmlSignal(QVariant)),
                         &myClass, SLOT(cppSlot(QVariant)));


    return app.exec();
}

My myclass.h

#ifndef MYCLASS_H
#define MYCLASS_H
#include <QDebug>
#include <QString>
#include <QList>



class MyClass : public QObject
{
    Q_OBJECT
public:
    MyClass(QObject *parent = 0);
signals:
public slots:
    void cppSlot(QVariant &msg);
};

#endif // MYCLASS_H

My myclass.cpp

#include "myclass.h"

MyClass::MyClass(QObject *parent):
    QObject(parent)
{

}
void MyClass::cppSlot(QVariant &msg){
    qDebug() << "c++: bien reçu chef " << msg;
}

I don't understand why I can't put a QVariant parameter in this signal. Any help is welcome :)

2
Have you tried using var (instead of variant): The variant type is a generic property type. It is obsolete and exists only to support old applications; new applications should use var type properties instead.RvdK
Also do you want to explicitly use variant? listCloud is a list with strings, so QStringList would do as well.RvdK
I want to use variant because I need to pass list of string but also list of object. You think I should write property var listCloud instead of property vairant listCloud ?Cam

2 Answers

1
votes

Change your slot to receive his parameter by value, rather than by reference. Like this:

    void cppSlot(QVariant msg);

I think it has something to do with QML refusing to pass Window's property by reference. Anyway, Qt often sends signal by-value even if your signal/slot signature[s] declare arguments by-reference. For more on the topic see this and that

0
votes

Don't use references between QML and C++, they won't work.

void cppSlot(QVariant & msg);

You can also create Q_INVOKABLE function in C++ and call it directly from QML. Here is how this looks like:

main.cpp:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlProperty>
#include <QQmlComponent>
#include <QDebug>
#include "myclass.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);   
    QQmlApplicationEngine engine;

    auto myobject = new MyClass(&app);
    engine.rootContext()->setContextProperty(QStringLiteral("myobject"), myobject);

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

    return app.exec();
}

mycass.h:

#ifndef MYCLASS_H
#define MYCLASS_H
#include <QDebug>
#include <QString>
#include <QList>

class MyClass : public QObject
{
    Q_OBJECT
public:
    MyClass(QObject *parent = 0);

    Q_INVOKABLE void cppSlot(QVariant msg);
};
#endif // MYCLASS_H

myclass.cpp:

#include "myclass.h"

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

void MyClass::cppSlot(QVariant msg)
{
    qDebug() << "c++: bien reçu chef " << msg;
}

main.qml:

import QtQuick 2.4
import QtQuick.Layouts 1.1
import Material.ListItems 0.1 as ListItem
import Material.Extras 0.1
import QtQuick.Controls 1.3 as QuickControls
import QtQuick.Controls 1.4
import Material 0.2

Window 
{
    visible: true
    property var listCloud: ["nuage1", "nuage2", "nuage3", "nuage4"]
    id: item
    width: 100; height: 100

    Rectangle
    {
        id:sousRect
        color:"red"
        width:100; height:100

        Button
        {
            id:buttonTest
            onClicked: myobject.cppSlot(listCloud)
        }
    }
} 

But if you like to use SIGNAL SLOTS there is Connections Object in QML. Your main.qml will look then like that:

Window 
{
    visible: true
    property var listCloud: ["nuage1", "nuage2", "nuage3", "nuage4"]
    id: item
    width: 100; height: 100

    Connections
    {
        target: buttonTest
        onClicked: myobject.cppSlot(listCloud)
    }

    Rectangle
    {
        id:sousRect
        color:"red"
        width:100; height:100

        Button
        {
            id:buttonTest
        }
    }
}

Q_INVOKABLE is nothing else as an public SLOT, it will be called through meta-object system.