I exposed a pointer variable to qml like this:
Fruit:
class Fruit : public QObject
{
Q_OBJECT
Q_PROPERTY(int qualityGrade READ qualityGrade WRITE setQualityGrade NOTIFY qualityGradeChanged)
Q_PROPERTY(bool organic READ organic WRITE setOrganic NOTIFY organicChanged)
public:
int qualityGrade() const
{
return m_qualityGrade;
}
bool organic() const
{
return m_organic;
}
public slots:
void setQualityGrade(int qualityGrade)
{
if (m_qualityGrade == qualityGrade)
return;
m_qualityGrade = qualityGrade;
emit qualityGradeChanged(m_qualityGrade);
}
void setOrganic(bool organic)
{
if (m_organic == organic)
return;
m_organic = organic;
emit organicChanged(m_organic);
}
signals:
void qualityGradeChanged(int qualityGrade);
void organicChanged(bool organic);
private:
int m_qualityGrade = -1;
bool m_organic = false;
};
MyClass.h:
class MyClass : public QObject
{
Q_OBJECT
Q_PROPERTY(Fruit* featuredFruit READ featuredFruit WRITE setFeaturedFruit NOTIFY featuredFruitChanged)
public:
explicit MyClass(QObject *parent = nullptr);
~MyClass();
Fruit* featuredFruit() const
{
return m_featuredFruit;
}
public slots:
void setFeaturedFruit(Fruit* featuredFruit)
{
if (m_featuredFruit == featuredFruit)
return;
m_featuredFruit = featuredFruit;
emit featuredFruitChanged(m_featuredFruit);
}
signals:
void featuredFruitChanged(Fruit* featuredFruit);
private:
Fruit* m_featuredFruit = nullptr;
};
MyClass.cpp:
MyClass::MyClass(QObject *parent) : QObject(parent)
{
m_featuredFruit = new Fruit();
m_featuredFruit->setQualityGrade(2);
QTimer *timer = new QTimer();
connect(timer, &QTimer::timeout, this, [=]() {
//m_featuredFruit->deleteLater(); //<--- activating these two lines causes to force working featuredFruitChanged signal
//m_featuredFruit = new Fruit();
m_featuredFruit->setQualityGrade(5);
emit featuredFruitChanged(m_featuredFruit);
delete timer;
});
timer->start(5000);
}
MyClass::~MyClass()
{
m_featuredFruit->deleteLater();
m_featuredFruit = nullptr;
}
and I used it in QML as follow:
MyClass {
id: classObj
onFeaturedFruitChanged: console.log("original property shows an change");//<--- called as expected
}
Item {
property Fruit selectedFruit: classObj.featuredFruit //<--- binding qml defined property to C++ property
onSelectedFruitChanged: {
console.log("binded property recieved change signal");//<--- not called after changes!!!
alertAnimation.restart(); //<--- an example of usage
}
}
The problem is whenever I emit featuredFruitChanged
, the binding qml property does not received change signal.
What is wrong?! Is this a Qt Framework bug? Any suggestion?
Also I tried overloading equality operator in C++ without success
OK, I add some more precisions to my sample code in order to reproduce problem easier.
A typo in my sample code fixed (thanks @ihor-drachuk). The problem exist yet.
This issue is still here at Qt 5.15.8. Anyway, I found a workaround that I stated it as an answer.
I found a workaround. In the QML codes, change type of the property named selectedFruit
to the var
.
This causes the emitted signal to be propagated through proxied property.
MyClass {
id: classObj
onFeaturedFruitChanged: console.log("original property shows an change"); //<--- called as expected
}
Item {
// ╭── USE `var` INSTEAD. THIS IS A WORKAROUND.
property var selectedFruit: classObj.featuredFruit
onSelectedFruitChanged: {
console.log("binded property recieved change signal"); //<--- will be called as expected :)
alertAnimation.restart();
}
}