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_OBJECTQ_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.0Item {
width: 300; height: 200Connections{ 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("app.qml")); view.show(); return a.exec();
}
@ -
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)
-
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
}
}
@