Qt - Q_PROPERTY的NOTIFY信号未在MEMBER更改时发出

5

我有一个私有类成员变量status,每当它改变时,我想用它的值发射一个信号。因此,我使用Q_PROPERTY并指定一个带有NOTIFY的信号:

#ifndef CAMERACONTROL_H
#define CAMERACONTROL_H

#include <QObject>
#include <iostream>

class CameraControl : public QObject
{
        Q_OBJECT
        Q_PROPERTY(QString status MEMBER status NOTIFY statusChanged)
    private:
        QString status;

    public:
        explicit CameraControl(QObject *parent = nullptr);
        ~CameraControl();
        void changeStatus()
        {
            std::cout << "changeStatus called" << std::endl; // The function definitely gets called!
            this->status = "Change status again!";
        }

    public slots:
        void outputStatus(const QString &status) {
            std::cout << status.toStdString() << std::endl;
        }

    signals:
        void statusChanged(const QString &status);

};

#endif // CAMERACONTROL_H

我在构造函数内将 statusChanged 信号连接到 outputStatus 槽:

#include "CameraControl.h"

CameraControl::CameraControl(QObject *parent) :
    QObject(parent)
{

    this->cameraHandle = nullptr;

    this->connect(this, &CameraControl::statusChanged, this, &CameraControl::outputStatus);

    this->status = "Change status text";
}

运行应用程序并通过另一个对象更改状态时,我没有得到任何输出,也没有收到来自qt的关于此问题的消息。
请注意,这不是实际实现。status经常通过各种成员函数进行更改,而没有任何输出。然而,connect调用以及statusChanged和outputStatus的实现与本问题完全相同。
因为Q_PROPERTY具有与成员相同的名称,所以我认为这可能是一个问题,并将Q_PROPERTY更改为以下内容,但没有任何区别:
Q_PROPERTY(QString qstatus MEMBER status NOTIFY statusChanged)

有人知道问题出在哪里吗?


2
你必须显式地发出信号,只有 QML 对象会自动发出信号,以避免在 QML 中不必要地重新评估绑定。例如,在 MEMBER 属性没有显式 setter 的情况下,Qt 会在需要时自动发出该信号。 - eyllanesc
@eyllanesc 谢谢你,但在我的情况下 Q_PROPERTY 将是无用的,对吗? - goulashsoup
问题是,为什么你想要使用 Q_PROPERTY?我不知道你的目标是什么。 - eyllanesc
我的想法是让类在状态属性更改时自动发出信号,或更广泛地调用函数,而不使用额外的setter。 - goulashsoup
2
无法完成,没有什么是自动的,您将不得不使用一个setter增加约5行代码。:(。 Q_PROPERTY的目标不是这样的。 - eyllanesc
啊,好的,谢谢你的帮助。 - goulashsoup
1个回答

9

NOTIFY告诉Qt,当您更改属性时,将发出statusChanged信号。如果属性被修改,它也会导致Qt发出信号,但是当您更改支持属性的类成员时,它不会发出信号。它不会在更改属性值时发出信号。

您需要自己实现这个功能,例如:

void setStatus(QString value)
{
   if (value != status)
   {
      status = value;
      emit statusChanged;
   }
}

或者,如果您调用setProperty,这将自动导致信号被发出:

void setStatus(QString value)
{
    setProperty("status", value);
}

请注意,这种方法可能比实施先前的方法更慢,因为它涉及将值包装在QVariant中,然后通过对象元信息进行查找。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接