Reputation: 14081
I am new to QML and have a problem in accessing a property.property of a C++ object:
C++, frequency and station both are Qt metatype registered objects:
CStation *station = new CStation(...); // QObject
CFrequency *frequency = new CFrequency(..); // QObject
QQmlContext *qmlContext = viewer.rootContext();
qmlContext->setContextProperty("myatcstation", station);
qmlContext->setContextProperty("myfrequency", frequency);
QML:
RowLayout { ....
TextField {
text: myatcstation.toQString(true)
}
}
.... text: myfrequency.toQString(true)
This works, but when I write: text: myatcstation.frequency.toQString(true)
I do get TypeError: Object [object Object] has no method 'toQString'
frequency
is a property of class CStation
set as Q_PROPERTY(CFrequency frequency READ getFrequency)
Crosscheck in C++ works:
CFrequency test = station->property("frequency").value<CFrequency>();
-- Edit: Frank's answer --
Both classes are derived from QObject
, and it is not as per textbook as they are made copyable. I am aware of the Identity vs value situation.
Basically frequency is a value object, but I have made it QObject
based so I am able to use properties with it (see Any chance to use non QObject classes with QML ). In the example, toString
is Q_INVOKABLE
, frequency in the non-working case returns a copy of a QObject
derived CFrequency
object.
-- Edit: Further findings --
When I change the frequency property to return CFrequency*
instead of CFrequency
it does not work either. As I get TypeError: Cannot call method 'toQString' of undefined
the situation seems to be the same. CFrequency
alone works, but QML does not understand that myatcstation.frequency
is a frequency object which has toString
.
Upvotes: 4
Views: 2736
Reputation: 11
I solved a similar problem:
class TopObject : public QObject
{
Q_OBJECT
Q_PROPERTY(ValueObject* theValue ...
...
}
class ValueObject : public QObject
{
Q_OBJECT
Q_PROPERTY(QString value ...
...
}
In the main application:
qRegisterMetaType<ValueObject>("ValueObject");
qmlRegisterType<ValueObject>("com.name.comp", 1, 0, "ValueObject");
...->setContextProperty("topObject", new TopObject());
And in the qml code:
import com.name.comp 1.0
... {
text: topObject.theValue.value
...
It needed both, returning the property (ValueObject) as pointer and registering it with qmlRegisterType.
See also Exchange Data and Objects between C++ and QML and vice versa
Upvotes: 1
Reputation: 25155
CFrequency
isn't a QObject I assume, otherwise you wouldn't return it by value but by pointer. To make `toQString() callable from QML, it must be either Q_INVOKABLE or a slot, which means that CFrequency must be a QObject as well.
If a station has only one frequency, consider moving the relevant information into the station object, i.e. add the frequency information you need as properties to CStation.
To get updates when the frequency changes, consider to use a property such as Q_PROPERTY(QString frequencyAsString READ frequencyAsString NOTIFY frequencyAsStringChanged)
instead of toQString()
. Properties have the update mechanism "built-in" via property bindings, while there's no good way to tell QML that it should call toQString again because the frequency changed.
Upvotes: 1