QML nie zapisuje właściwości C++ w stosunku do komponentu i zmianie wartości składnika

0

Pytanie

Pracuję nad projektem QML. W interfejsie użytkownika, nad którym pracuję, muszę jak zaktualizować suwak z C++, jak i odczytać aktualną wartość w C++ z QML. Właściwości wydają się być dobrym rozwiązaniem. Do tej pory czytałem różne pytania TAK, że bezskutecznie Model dwustronne wiązania C++ w QML, Zmienione właściwości nie powodują alarmu itp... W moim aktualnym kodzie ogłosiłem właściwość w klasie 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;
...
}

I wystawił go w Qt z pomocą syngielton

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

Następnie przywiązał właściwości C++ do suwaka 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
        }*/
    }
}

Przyciąganie, wydaje się, działa. Mogę zmienić wartość myValue następnie emitują myValueChanged aby zaktualizować QML, to suwak. Ale biorąc pod uwagę to myClass.myValue ograniczona slider.value. Ja bym zasugerował, że obie wartości są aktualizowane jednocześnie. Ale przeciąganie suwaka pokazuje, że mają one różne znaczenia. Poniżej to, co jest drukowane w konsoli, gdy przeciągam swój suwak.

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

Ponadto setMyValue wydaje się, że on nie jest wywoływana, jeśli nie jest spełniony wyraźny cel, np. myClass.myValue = 0. Ja również bezskutecznie próbował składnik przyciągania. Dlaczego tak jest i czy mogę zaktualizować właściwość C++ za każdym razem, gdy pionowymi suwak?

Qt: 6.2.1
Kompilator: brzęk/gcc
SYSTEM operacyjny: Windows/Linux

Aktualizacja: przetestowano inaczej wiązanie. Wciąż piszę ten sam wynik

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

Aby zaktualizować właściwość C++ z QML, można użyć 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

co się dzieje, kiedy myClass.myValue będzie aktualizowana i będzie działać jego myValueChanged?
folibis

@folibis To aktualizuje właściwość "wartość suwaka". Oczywiście, w setMyValue metoda musi zaczynać się od porównania nowej wartości z bieżącą wartością i wydawania myValueChanged tylko w tym przypadku, jeśli wartość jest naprawdę zostało zaktualizowane. W innym przypadku możesz zobaczyć pętlę przyciągania
Jakub Warchoł

Dziękuję za odpowiedź. Próbowałem proponowane rozwiązanie. Ale nadal nie widzę ani wywołanego seter, ani wartości console.log("myClass.myValue = " + myClass.myValue) zmodyfikowany.
Mary Chang

@MaryChang W powyższym kodzie widać console.log("myClass.myValue = " + myClass.myValue) gdy będziesz przesuwać suwak. Zobaczyć myClass.myValue wartość zmieniło, spójrz na połączenia
Jakub Warchoł
0

Oto minimalny przepływ przykład suwaka dwustronnej aktualizacji:

main.cpp:

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

dane.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

Pomijasz sygnał po zmianie wartości:

Q_PROPERTY(double myValue READ getMyValue WRITE setMyValue NOTIFY myValueChanged)

Oznacza to, że obiecujesz, że wyślesz myValueChanged сигнализируйте za każdym razem, gdy kod C++ zmienia wartość. W ten sposób, powinno zadziałać następujący:

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

W innych językach

Ta strona jest w innych językach

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