如何在依赖属性更改时重新计算绑定到 qml 属性的 c++ 函数

How to re-evaluate c++ function bound to qml property on dependent property change?

本文关键字:属性 绑定 计算 qml c++ 函数 新计算 依赖      更新时间:2023-10-16

我想将C++类的方法绑定到 QML 组件属性,并在依赖属性更改时重新评估它。以下 QML 组件可以执行我想要的操作:

// Converter.qml:
import QtQuick 2.0
QtObject {
    property double rate: 1
    function exchange(amount) { return amount * rate }
}

如果我将 exchange 函数的结果分配给这样的属性,

Text { text: converter.exchange(100) }

文本元素将在更改rate时自动更新。 这适用于 QML 组件,但我不知道如何使用 C++ 类来做到这一点。

我想在C++中实现一个功能等效的类:

#include <QObject>
class Convert : public QObject
{
    Q_OBJECT
    Q_PROPERTY(double rate READ rate WRITE setRate NOTIFY rateChanged)
public:
    explicit Convert(QObject *parent = 0)
        : QObject(parent), m_rate(1.0)
    { }
signals:
    void rateChanged();
public slots:
    double exchange(double amount) { return m_rate * amount; }
    double rate() { return m_rate; }
    void setRate(double r) {
        m_rate = r;
        emit rateChanged();
    }
private:
    double m_rate;
};

rate属性可以从 QML 访问,但更改它不会向 QML 引擎发出应重新评估"交换"的信号。

这是我的主要.qml:

// main.qml
import QtQuick 2.1
import QtQuick.Controls 1.1
import Utils 1.0
ApplicationWindow {
    width: 300; height: 200
    visible: true
//    Converter { id: converter; rate: rateField.text }
    CppConverter { id: converter; rate: rateField.text }
    Column {
        TextField { id: rateInput; text: '0.41' }
        TextField { id: amountInput; text: '100.00' }
        Text { id: output; text: converter.exchange(amountField.text).toFixed(2) }
    }
}

如果我启用CppConverter,则当我更改amountInput时输出会更新,但在更改rateInput时不会更新。 如果我在 QML 转换器元素中发表评论,则更新工作正常。

使用 QML

转换器,QML 运行时识别对速率属性的依赖关系,并在速率更改时重新评估交换函数。 如何指示 QmlEngine 在C++版本中执行相同的操作?

目前没有办法做到这一点。

不过,我不认为依赖像这样重新评估的函数是一种好的做法。必要时应显式调用它:

Connections {
    target: converter
    onRateChanged: output.text = converter.exchange(amountField.text)
}

或者将 exchange(( 转换为属性,并以声明方式而不是命令性方式处理它(代码不完整或未经测试(:

class Convert : public QObject
{
    // ...
    Q_PROPERTY(double amount READ amount WRITE setAmount NOTIFY amountChanged)
    Q_PROPERTY(double exchange READ exchange NOTIFY exchangeChanged)
    // ...
public:
    double exchange() { return m_rate * m_amount; }
private:
    double m_rate;
    double m_amount;
};

然后,您需要在适当的位置发出各种*更改信号等。