Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Q_物业系统未按预期运行_C++_Qt_Qobject - Fatal编程技术网

C++ Q_物业系统未按预期运行

C++ Q_物业系统未按预期运行,c++,qt,qobject,C++,Qt,Qobject,我打算在qml引擎的上下文中使用这个类,所以为了使用属性绑定,我设置了这些Q_属性宏。我想使用MEMBER关键字并自动发出notify信号 class InterfaceBackend : public QObject { Q_OBJECT Q_PROPERTY(quint8 current_view MEMBER m_current_view NOTIFY sCurrentViewChanged) Q_PROPERTY(quint8 future_view MEMBER

我打算在qml引擎的上下文中使用这个类,所以为了使用属性绑定,我设置了这些Q_属性宏。我想使用MEMBER关键字并自动发出notify信号

class InterfaceBackend : public QObject
{
    Q_OBJECT
    Q_PROPERTY(quint8 current_view MEMBER m_current_view NOTIFY sCurrentViewChanged)
    Q_PROPERTY(quint8 future_view MEMBER m_future_view NOTIFY sFutureViewChanged)

public:
    explicit InterfaceBackend(QObject *parent = 0);
    ~InterfaceBackend();

    quint8 getCurrentView() { return this->m_current_view; }
    quint8 getFutureView() { return this->m_future_view; }

private:
    quint8 m_current_view;
    quint8 m_future_view;
    QByteArray m_selected_language;

public slots:
    void onLanguageSelected(QByteArray language);

private slots:


signals:
    void sCurrentViewChanged(quint8 current_view);
    void sFutureViewChanged(quint8 future_view);

};


InterfaceBackend::InterfaceBackend(QObject *parent) : QObject(parent)
{
    this->setObjectName("backend");
    QObject::connect(this, &InterfaceBackend::sFutureViewChanged, []() {qDebug() << "sFutureViewChanged";});
    this->m_current_view=1;
    this->m_future_view=1;
}

InterfaceBackend::~InterfaceBackend()
{

}

void InterfaceBackend::onLanguageSelected(QByteArray language)
{
    this->m_selected_language=language;
    this->m_future_view=2;
}
类接口备份:公共QObject
{
Q_对象
Q_属性(quint8当前_视图成员m_当前_视图通知sCurrentViewChanged)
Q_属性(quint8 future_view成员m_future_view通知sFutureViewChanged)
公众:
显式接口备份(QObject*parent=0);
~InterfaceBackend();
quint8 getCurrentView(){返回此->当前视图;}
quint8 getFutureView(){返回此->m_future_view;}
私人:
五次8 m_当前视图;
五分之八的未来观;
QByteArray m_选择的_语言;
公众时段:
仅选择void语言(QByteArray语言);
专用插槽:
信号:
void sCurrentViewChanged(当前视图);
作废未来视图已更改(五次未来视图);
};
InterfaceBackend::InterfaceBackend(QObject*父对象):QObject(父对象)
{
此->setObjectName(“后端”);
连接(此,&InterfaceBackend::sFutureViewChanged,[](){qDebug()m_current_view=1;
此->m_future_view=1;
}
InterfaceBackend::~InterfaceBackend()
{
}
void InterfaceBackend::onLanguageSelected(QByteArray语言)
{
此->m_选择的_语言=语言;
此->m_future_view=2;
}
qt文档说:

NOTIFY信号是可选的。如果已定义,则应指定该类中的一个现有信号,该信号在属性值更改时发出。成员变量的NOTIFY信号必须采用零或一个参数,该参数必须与属性的类型相同。该参数将采用属性的新值。NOTIFY信号should仅在属性确实已更改时发出,以避免绑定在QML中被不必要地重新计算。例如,对于没有显式setter的成员属性,Qt在需要时自动发出该信号

但每当我调用插槽时,信号永远不会被调用,属性也不会在qml模型中更新,这是怎么回事!?

正如您在文章中看到的:

Q_属性中的New关键字:MEMBER允许您将属性绑定到类成员,而无需使用getter或setter

所以您应该删除getter,结果代码如下所示

class InterfaceBackend : public QObject
{
    Q_OBJECT
    Q_PROPERTY(quint8 current_view MEMBER m_current_view NOTIFY sCurrentViewChanged)
    Q_PROPERTY(quint8 future_view MEMBER m_future_view NOTIFY sFutureViewChanged)

public:
    explicit InterfaceBackend(QObject *parent = 0)
        : QObject(parent)
    {
        this->setObjectName("backend");
        QObject::connect(this, &InterfaceBackend::sFutureViewChanged, []() { qDebug() << "sFutureViewChanged";});
        this->m_current_view=1;
        emit sCurrentViewChanged();
        this->m_future_view=1;
        emit sFutureViewChanged();
    }
    ~InterfaceBackend() = default;

private:
    quint8 m_current_view;
    quint8 m_future_view;
    QByteArray m_selected_language;

public slots:
    void onLanguageSelected(QByteArray language) {
        this->m_selected_language=language;
        this->m_future_view=2;
        emit sFutureViewChanged();
    }

signals:
    void sCurrentViewChanged();
    void sFutureViewChanged();

};
类接口备份:公共QObject
{
Q_对象
Q_属性(quint8当前_视图成员m_当前_视图通知sCurrentViewChanged)
Q_属性(quint8 future_view成员m_future_view通知sFutureViewChanged)
公众:
显式接口备份(QObject*parent=0)
:QObject(父对象)
{
此->setObjectName(“后端”);
连接(此,&InterfaceBackend::sFutureViewChanged,[](){qDebug()m_current_view=1;
emit sCurrentViewChanged();
此->m_future_view=1;
发出sFutureViewChanged();
}
~InterfaceBackend()=默认值;
私人:
五次8 m_当前视图;
五分之八的未来观;
QByteArray m_选择的_语言;
公众时段:
仅无效所选语言(QByteArray语言){
此->m_选择的_语言=语言;
此->m_future_view=2;
发出sFutureViewChanged();
}
信号:
void sCurrentViewChanged();
void sFutureViewChanged();
};

每个Q_属性必须有读公共方法和写公共槽,而且信号永远不会自动发出,您应该在成员更改时发出它

class InterfaceBackend : public QObject
{
    Q_OBJECT
    Q_PROPERTY(quint8 current_view MEMBER m_current_view READ currentView WRITE setCurrentView NOTIFY sCurrentViewChanged)
    Q_PROPERTY(quint8 future_view MEMBER m_future_view READ futureView WRITE setFutureView NOTIFY sFutureViewChanged)

public:
    explicit InterfaceBackend(QObject *parent = 0);
    ~InterfaceBackend();

    quint8 currentView() const
    {
        return m_current_view;
    }
    quint8 futureView() const
    {
        return m_future_view;
    }

private:
    quint8 m_current_view;
    quint8 m_future_view;
    QByteArray m_selected_language;

public slots:
    void onLanguageSelected(QByteArray language);

    void setCurrentView(quint8 current_view)
    {
        if (m_current_view == current_view)
            return;

        m_current_view = current_view;
        emit sCurrentViewChanged(m_current_view);
    }

    void setFutureView(quint8 future_view)
    {
        if (m_future_view == future_view)
            return;

        m_future_view = future_view;
        emit sFutureViewChanged(m_future_view);
    }

private slots:


signals:
    void sCurrentViewChanged(quint8 current_view);
    void sFutureViewChanged(quint8 future_view);

};


InterfaceBackend::InterfaceBackend(QObject *parent) : QObject(parent)
{
    this->setObjectName("backend");
    QObject::connect(this, &InterfaceBackend::sFutureViewChanged, []() {qDebug() << "sFutureViewChanged";});
    this->m_current_view=1;
    this->m_future_view=1;
}

InterfaceBackend::~InterfaceBackend()
{

}

void InterfaceBackend::onLanguageSelected(QByteArray language)
{
    this->m_selected_language=language;
    this->m_future_view=2;
}
类接口备份:公共QObject
{
Q_对象
Q_属性(quint8 current_view成员m_current_view READ currentView WRITE setCurrentView NOTIFY sCurrentViewChanged)
Q_属性(quint8 future_view成员m_future_view读取futureView写入设置futureView通知sFutureViewChanged)
公众:
显式接口备份(QObject*parent=0);
~InterfaceBackend();
quint8 currentView()常量
{
返回m_当前视图;
}
quint8 futureView()常量
{
返回m_未来视图;
}
私人:
五次8 m_当前视图;
五分之八的未来观;
QByteArray m_选择的_语言;
公众时段:
仅选择void语言(QByteArray语言);
无效setCurrentView(当前视图)
{
如果(m_当前_视图==当前_视图)
回来
m_current_view=当前_view;
发射sCurrentViewChanged(m_当前_视图);
}
void setFutureView(第8组futureview)
{
if(m_future_view==future_view)
回来
m_future_view=future_view;
发射未来视图已更改(m_未来视图);
}
专用插槽:
信号:
void sCurrentViewChanged(当前视图);
作废未来视图已更改(五次未来视图);
};
InterfaceBackend::InterfaceBackend(QObject*父对象):QObject(父对象)
{
此->setObjectName(“后端”);
连接(此,&InterfaceBackend::sFutureViewChanged,[](){qDebug()m_current_view=1;
此->m_future_view=1;
}
InterfaceBackend::~InterfaceBackend()
{
}
void InterfaceBackend::onLanguageSelected(QByteArray语言)
{
此->m_选择的_语言=语言;
此->m_future_view=2;
}

要给出技术上更准确的答案:

Q_属性
中的
成员
将告诉moc(元对象编译器)当通过元对象访问属性时,它应该直接使用成员,而不是getter或setter方法。因此,moc将在内部生成一个setter方法,该方法设置成员,并发出信号-它基本上只是为您编写getter/setter。因为更改成员需要发出信号更改信号,当从元对象系统写入属性时,会自动执行此操作。因此,调用:

backend->setProperty("future_view", future_view);
将正确发出更改的信号。这是使用成员时提供的唯一保证。通过元属性进行的更改将触发更改信号。此
void onLanguageSelected(QByteArray language)
{
    this->m_selected_language=language;
    this->m_future_view=2;
    emit sFutureViewChanged();
}
    Q_PROPERTY(quint8 future_view READ futureView NOTIFY sFutureViewChanged)
class InterfaceController : public QObject
{
    Q_OBJECT
    Q_PROPERTY(quint8 current_view READ getCurrentView WRITE setCurrentView NOTIFY sCurrentViewChanged)
    Q_PROPERTY(quint8 future_view READ getFutureView WRITE setFutureView NOTIFY sFutureViewChanged)

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

    //getters
    quint8 getCurrentView() { return this->m_current_view; }
    quint8 getFutureView() { return this->m_future_view; }

    //setters
    Q_INVOKABLE void setCurrentView(quint8 current_view) { if(this->m_current_view!=current_view) {this->m_current_view=current_view; emit sCurrentViewChanged(this->m_current_view);} }
    Q_INVOKABLE void setFutureView(quint8 future_view) { if(this->m_future_view!=future_view) {this->m_future_view=future_view; emit sFutureViewChanged(this->m_future_view);} }

private:
    quint8 m_current_view;
    quint8 m_future_view;

    QByteArray m_selected_language;

public slots:
    void onLanguageSelected(QByteArray language);

private slots:


signals:
    void sCurrentViewChanged(quint8 current_view);
    void sFutureViewChanged(quint8 future_view);

};

InterfaceController::InterfaceController(QObject *parent) : QObject(parent)
{
    this->m_current_view=1;
    this->m_future_view=1;
}

void InterfaceController::onLanguageSelected(QByteArray language)
{
    this->m_selected_language=language;
    this->setFutureView(2);
}
id: root
property int current_view: 1
property int future_view: 1

Connections {
    target: root
    onCurrent_viewChanged: { backend.setCurrentView(current_view); }
    onFuture_viewChanged: { backend.setFutureView(future_view); }
}

Connections {
    target: backend
    onSCurrentViewChanged: { if(root.current_view!=current_view) {root.current_view=current_view;} }
    onSFutureViewChanged: { if(root.future_view!=future_view) {root.future_view=future_view;} }
}