C++ Q_物业系统未按预期运行
我打算在qml引擎的上下文中使用这个类,所以为了使用属性绑定,我设置了这些Q_属性宏。我想使用MEMBER关键字并自动发出notify信号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
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;} }
}