如何覆盖 Q_Property?
Posted
技术标签:
【中文标题】如何覆盖 Q_Property?【英文标题】:How to override a Q_Property? 【发布时间】:2015-04-16 18:40:53 【问题描述】:考虑这些类:
Class A : public QObject
...
Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)
virtual int value() return m_value;
void setValue(int v) m_value = v; Q_EMIT valueChanged();
...
;
Class B : public A
...
int value() return m_value * 2;
...
;
访问属性值时,直接调用Class A的方法,而不是Class B的方法。
到目前为止,为了解决这个明显的限制,我复制了属性代码并连接了每个类的信号。
这是最好的解决方案吗?
有没有人发现潜在的问题(由于属性名称相同)?
【问题讨论】:
【参考方案1】:来自 Qt 文档:
可以继承 READ、WRITE 和 RESET 函数。他们还可以 是虚拟的。当它们在多个类中被继承时 使用继承,它们必须来自第一个继承的类。
只需将访问器设为虚拟,它们就会从 vtable 中调用,因此您将获得适用于每个不同子类型的正确函数。
【讨论】:
也许我遗漏了什么,但这就是我在提供的示例中所做的。 嗯.. 我想我是... :) 我重新测试过,这次一切正常。显然,在 QML 上,在设置值时不会调用 onValueChanged 方法:B value: 2 onValueChanged: console.log("value " + value)
您可能需要清理项目并重建。当您进行更改时,Qt 经常会出现问题,让所有内容保持最新。【参考方案2】:
Q_PROPERTY ... // the same
signals:
void valueChanged(int value);
public:
int value() const return m_value;
virtual void setValue(int newValue)
m_value = newValue;
emit valueChanged( value() );
class B : public A
public:
void setValue(int newValue) A::setValue(newValue *2);
变体 2(稍微好一点):
Class A
Q_PROPERTY
signals:
void valueChanged(int value);
public:
int value(...
void setValue(int value)
changeValue(value); // to call virtual changeValue
emit valueChanged( m_value );
protected:
virtual void changeValue(int newValue)
m_value = newValue;
...
// We dont touch public methods, but protected:
Class B : public A
protected:
/*virtual*/ void changeValue(int newValue)
A::changeValue(newValue *2);
【讨论】:
我喜欢你巧妙的解决方案,但只要简单的“事情”有效,我就会坚持下去! BTW 始终在设置和发出信号之前检查新值是否不等于现有值。这样可以避免连接和绑定循环。 解决方案 2 在 B 实例上设置值时不起作用,因为在这种情况下不会触发通知信号。发射需要转移到 changeValue 实现,当然应该只在值实际发生变化时触发。以上是关于如何覆盖 Q_Property?的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 Q_PROPERTY 向 QML 公开指向 Q_GADGET 的指针
Qt:如何在 C++ 端而不是 QML 上监视 Q_PROPERTY 更改