【问题标题】:How to override a Q_Property?如何覆盖 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的方法。

到目前为止,为了解决这个明显的限制,我复制了属性代码并连接了每个类的信号。

这是最好的解决方案吗?

有没有人发现潜在的问题(由于属性名称相同)?

【问题讨论】:

    标签: qt polymorphism overriding qt5.4 qproperty


    【解决方案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 实现,当然应该只在值实际发生变化时触发。
    猜你喜欢
    • 1970-01-01
    • 2021-12-21
    • 2021-06-26
    • 1970-01-01
    • 2015-09-09
    • 1970-01-01
    • 2012-12-17
    • 2020-07-28
    • 2012-02-25
    相关资源
    最近更新 更多