0
votes

I have a C++ property

 Q_PROPERTY(QList<qreal> XTickPos MEMBER _xTickPos);

which I want to use in a Repeater. In the same QML file, the c++ class has been given the id

id: pw

The repeater looks like this

        Item {
            anchors.fill: parent
            visible: true
            Repeater {
                model: pw.XTickPos.length
                Rectangle{
                    height: 50
                    width: 2
                    x: pw.XTickPos[index]
                    y:10
                    visible: true
                    color: "black"
                    border.width: 2
                }
              }
        }

However, nothing is drawn on the screen. If instead I make property in the QML file:

 var xTickPos = []

and set it via a Q_Invokable function in c++

 Q_INVOKABLE QList<qreal> getXTickPositions();

and in QML

 root.xTickPos=pw.getXTickPositions();

and use the QML property xTickPos as model in the above repeater it is working. I checked that pw.XTickPos is correctly filled via a console.log

What am I missing here?

1
Use a proper model, that will notify your repeater when elements are added. If QML does not know that something has been added to your list, it wont refresh. - derM
I thought that if it is a Q_PROPERTY it would automatically send a signal if it changed? - numberCruncher
No. The better syntax for Q_PROPERTY is: Q_PROPERTY(type name READ name WRITE setName NOTIFY nameChanged) - where you will emit the signal nameChanged() in the setter, setName(...). Then you will have a signal emited. But also only if you set a new list - not when you add something to the list. If you look at doc.qt.io/qt-5/qlist.html you will see that QList does not even have a signal that could notify the length has changed. - derM
Since the QList won't notify a change of the contained data, it is not advisable to use it as a model (same as the QML/JS Array). Use a doc.qt.io/qt-5/qabstractitemmodel.html instead. You might take a look at the convenient QQmlObjectListModel you can find here: github.com/Cavewhere/lib-qt-qml-tricks - derM
Regarding performance: Is it costly to use a full model? I am asking because all I need to do is set some (e.g. 10) rectangles, and this needs to be updated fast, e.g. on a window size change. Also: Apart from the notification, why does my above approach not work? - numberCruncher

1 Answers

1
votes

This one is kinda tricky.

The documentation states that you can use a JS array as a model, and it does state that QList<qreal> is automatically converted to a JS array when returned to QML.

But it seems that you can't use a QList<qreal> that is automatically converted to a JS array as a model. Go figure...

Naturally, it is preferable to have a proper model with its proper notifications for top efficiency. But in case you really want to go for the list property, it appears you will have to do the conversion manually in a getter:

QVariantList model() {
  QVariantList vl;
  for (auto const & v : yourList) vl.append(v);
  return vl;
}

Amazingly, although Qt supposedly makes that conversion automatically, it doesn't seem to be able to make a QVariantList from a QList<qreal>.

That's Qt for you...