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

时间:2014-10-13 04:35:57

标签: c++ qt binding qml signals-slots

我想将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时,Text元素会自动更新。这适用于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;
};

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

这是我的main.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 Converter元素中发表评论,那么更新工作正常。

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

1 个答案:

答案 0 :(得分:3)

目前无法做到这一点。

我不认为依赖于像这样重新评估的功能是一种很好的做法。您应该在必要时明确地调用它:

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;
};

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