How to send Qt signals with non basic types to a QML script



  • Hello !!

    I have two classes, Map and Position, both are derivate from QObject.
    I have a QML script which display a Position object.

    I'm trying to send a signal (from a Map object) holding a Position object to update my QML srcipt. But i got the following message when the signal occurs:

    bq. QMetaProperty::read: Unable to handle unregistered datatype 'Position' for property 'QDeclarativeBoundSignalParameters::newPosition'

    bq. app.qml:10: TypeError: Result of expression 'newPosition' [undefined] is not an object.

    Here my code:

    @
    #ifndef POSITION_H
    #define POSITION_H

    #include <QObject>

    class Position : public QObject
    {
    Q_OBJECT
    Q_PROPERTY(double latitude READ latitude WRITE setLatitude)
    Q_PROPERTY(double longitude READ longitude WRITE setLongitude)

    public:
    Position(double latitude = 0, double longitude = 0,QObject *parent = 0);
    Position(const Position & other);
    Position & operator =( const Position & other);
    bool operator !=(const Position &);

    double latitude();
    void setLatitude(double);
    
    double longitude();
    void setLongitude(double);
    

    private:
    double m_lat;
    double m_lon;
    };

    #endif // POSITION_H
    @

    @
    #ifndef MAP_H
    #define MAP_H

    #include <QObject>

    #include "position.h"

    class Map : public QObject
    {
    Q_OBJECT

    Q_PROPERTY(Position center READ center WRITE setCenter NOTIFY centerChanged)
    

    public:
    explicit Map(QObject *parent = 0) :
    QObject(parent)
    {}

    Position center() const{
        return m_center;
    }
    void setCenter(const Position & other){
        if( m_center != other ){
            m_center = other;
            emit centerChanged(m_center);
        }
    }
    

    signals:
    void centerChanged(Position newPosition);

    private:
    Position m_center;
    };

    #endif // MAP_H
    @

    @
    import QtQuick 1.0
    import Localisation 1.0

    Item {
    width: 300; height: 200

    Connections{
        target: myMap
        onCenterChanged: {
            //perform action with newPosition, e.g :
            text.text = newPosition.latitude + ", " + newPosition.longitude
        }
    }
    
    Text{
        id: text
        anchors.centerIn: parent
        text: "Wait an update"
    }
    

    }
    @

    @
    #include <QApplication>
    #include <QtDeclarative>
    #include <QDeclarativeView>

    #include "map.h"
    #include "position.h"

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);

    qmlRegisterType<Position>("Localisation",1,0,"Position");
    
    Map myMap;
    QDeclarativeView view;
    view.rootContext()->setContextProperty("myMap",&myMap);
    view.setSource(QUrl::fromLocalFile&#40;"app.qml"&#41;);
    view.show();
    
    return a.exec&#40;&#41;;
    

    }
    @



  • Hello,

    first of all, i would use QDeclarativeItem instead of QObject for using an object in QML.

    Then i may use the object connections, but the target had to be an QML item, which is not exactly in your code (it is more a "binding" done with setContextProperty)



  • Try with:

    @
    qmlRegisterType<Position>();
    @

    and if it doesn't work maybe additionally with:

    @
    qmlRegisterType<Map> ();
    @



  • You know that instead of adding new clas you could use QPointF:
    @
    //.h file
    class Map : public QObject
    {
    Q_OBJECT
    Q_PROPERTY(QPointF center READ getCenter NOTIFY centerChanged)

    public:
    explicit Map(QObject *parent = 0);

    inline QPointF getCenter() const;
    void setCenter(const QPointF& aCenter);
    

    signals:
    void centerChanged();
    public slots:
    void blabla();

    private:
    QPointF m_center;
    };

    QPointF Map::getCenter() const
    {
    return m_center;
    }

    //.cpp file
    void Map::setCenter(const QPointF &aCenter)
    {
    if (aCenter == m_center)
    return;

    m_center = aCenter;
    emit centerChanged();
    

    }

    //Part of qml file
    Connections {
    target: myMap
    onCenterChanged: {
    myTxt.text = "x " + myMap.center.x + " y " + myMap.center.y
    }
    }
    @

    If you want to use longitude and latitude keywords you can do:
    @
    //.h file
    Q_PROPERTY(QVariant center READ getCenter NOTIFY centerChanged)
    //...
    QVariant getCenter() const;

    //.cpp file
    QVariant Map::getCenter() const
    {
    QMap<QString, QVariant> centerMap;
    centerMap.insert("longitude",m_center.x());
    centerMap.insert("latitude",m_center.y());

    return centerMap;
    

    }

    //.qml file
    Connections {
    target: myMap
    onCenterChanged: {
    myTxt.text = "x " + myMap.center.longitude + " y " + myMap.center.latitude
    }
    }
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.