QML не записывает свойство C++ при привязке к компоненту и изменении значения компонента

0

Вопрос

Я работаю над проектом QML. В пользовательском интерфейсе, над которым я работаю, мне нужно как обновить слайдер с C++, так и прочитать текущее значение в C++ из QML. Свойства, похоже, являются правильным решением. До сих пор я читал разные вопросы по ТАК что безуспешно Модель двусторонней привязки C++ в QML, Измененные свойства не вызывают сигнала и т. Д... В моем текущем коде я объявил свойство в своем классе C++

class MyClass : public QObject {
    Q_OBJECT
public:
    MyClass(QObject*);
    Q_PROPERTY(double myValue READ getMyValue WRITE setMyValue NOTIFY myValueChanged)

    void setMyValue(double n) {
        std::cerr << "myValue  being update: " << n << "\n";
        myValue = n;
    }

    double myValue = 30;
...
}

И выставил его в Qt с помощью синглтона

qmlRegisterSingletonInstance("com.me.test", 1, 0, "MyClass", &myClass);

Затем привязал свойство C++ к ползунку QML

import com.me.test
ApplicationWindow {
    Slider {
        id: slider
        height: 30
        width: 100
        from: 0
        to: 100
        value: myClass.myValue
        onValueChanged {
            console.log("value = " + value)
            console.log("myClass.myValue = " + myClass.myValue)
        }

        /* Doesn't help
        Binding {
            target: slider
            property: "value"
            value: myClass.myValue
        }*/
    }
}

Привязка, кажется, работает. Я могу изменить значение myValue затем испускают myValueChanged чтобы обновить QML, это слайдер. Но, учитывая это myClass.myValue ограничивается slider.value. Я бы предположил, что оба значения обновляются одновременно. Но перетаскивание ползунка показывает, что они имеют разные значения. Ниже приведено то, что печатается в консоли, когда я перетаскиваю свой ползунок.

qml: value = 19.863013698630137
qml: myClass.myValue = 30

Кроме того setMyValue кажется, что он не вызывается, если не выполнено явное назначение, например myClass.myValue = 0. Я также безуспешно пробовал компонент привязки. Почему это так и могу ли я обновлять свойство C++ всякий раз, когда перетаскиваю ползунок?

Qt: 6.2.1
Компилятор: clang/gcc
ОС: Windows/Linux

Обновление: протестировано обратное связывание. Все еще печатаю тот же результат

import com.me.test
ApplicationWindow {
    Slider {
        id: slider
        height: 30
        width: 100
        from: 0
        to: 100
        value: myClass.myValue
        onValueChanged {
            console.log("value = " + value)
            console.log("myClass.myValue = " + myClass.myValue)
        }
        Binding {
            target: myClass
            property: "myValue"
            value: slider.value
        }
    }
}
c++ qml qt qt6
2021-11-24 06:49:49
3
0

Чтобы обновить свойство C++ из QML, вы можете использовать Binding:

import com.me.test
ApplicationWindow {
    Slider {
        id: slider
        height: 30
        width: 100
        from: 0
        to: 100
        value: myClass.myValue
        onValueChanged {
            console.log("value = " + value)
            console.log("myClass.myValue = " + myClass.myValue)
        }
         // C++ property was bounded to QML above, now we should bind QML to C++
        Binding {
            target: myClass 
            property: "myValue"
            value: slider.value
        }
    }
}
2021-11-24 09:12:14

что происходит, когда myClass.myValue будет обновляться и будет срабатывать его myValueChanged?
folibis

@folibis Это обновит свойство "значение слайдера". Конечно, в setMyValue метод должен начинаться с сравнения нового значения с текущим значением и выдавать myValueChanged только в том случае, если значение действительно было обновлено. В другом случае вы могли бы увидеть петлю привязки
Jakub Warchoł

Спасибо за ответ. Я попробовал предложенное решение. Но все еще не вижу ни вызываемого сеттера, ни значения console.log("myClass.myValue = " + myClass.myValue) измененный.
Mary Chang

@MaryChang В приведенном выше коде вы увидите console.log("myClass.myValue = " + myClass.myValue) когда вы будете перемещать ползунок. Видеть myClass.myValue значение изменилось, посмотрите на соединения
Jakub Warchoł
0

Вот минимальный рабочий пример ползунка двустороннего обновления:

main.cpp:

data dataObj;
engine.rootContext()->setContextProperty("dataCpp", (QObject*)&dataObj);

данные.h:

class data : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)
public:
    explicit data(QObject *parent = nullptr);
    int value(void);
    void setValue(int new_value);
public slots:
    void reset(void);
signals:
    void valueChanged();
private:
    int dataValue;
};

data.cpp:

data::data(QObject *parent) : QObject(parent)
{
    dataValue = 250;
}

int data::value()
{
    return dataValue;
}

void data::setValue(int new_value)
{
    if(dataValue != new_value)
    {
        qDebug() << "setting" << new_value;
        dataValue = new_value;
        emit valueChanged();
    }
}

void data::reset()
{
    if(dataValue != 0)
    {
        qDebug() << "resetting to 0";
        dataValue = 0;
        emit valueChanged();
    }
}

main.qml:

Slider {
    id: slider
    height: 50
    width: 500
    from: 0
    to: 500
    live: false
    value: dataCpp.value
    onValueChanged: dataCpp.value = value
}

Button{
    anchors.top: slider.bottom
    text: "Reset"
    onPressed: dataCpp.reset()
}
2021-12-14 13:21:29
0

Вы пропускаете сигнал при изменении значения:

Q_PROPERTY(double myValue READ getMyValue WRITE setMyValue NOTIFY myValueChanged)

Это означает, что вы обещаете, что отправите myValueChanged сигнализируйте всякий раз, когда код C++ изменяет значение. Таким образом, должно сработать следующее:

void setMyValue(double n) {
    std::cerr << "myValue  being update: " << n << "\n";
    myValue = n;
    emit(myValueChanged());
}
2021-12-14 15:18:53

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................