0

I have QAbstractListModel in c++ code and connected it with qml GridView of Butons by means of

QQmlApplicationEngine engine;
QQmlContext* context = engine.rootContext();
context->setContextProperty("keyboardModel", _keyboardModel);

The main goal is get global coordinates of Buttons in c++ code. For this purposes i find this Buttons with QQuickItem::childItems() function and get final coordinates with mapToGlobal().

Now, when i changed c++ model, qml GridView changed too. But, i cannot catch moment, when hierarchical QQuickItem tree fully refreshed (It needed for correct working QQuickItem::childItems())

GridView's signals onAdd, on Remove doesn't working, when new model has same amount of elements. GridView's signal onModelChanged triggered only, when i connected another model, not when i changed this one.

Is there any signal for recognizing, when hierarchical QQuickItem tree fully refreshed? Or there is any another method for dynamically getting Qml's object global coordinates?

Nikxp
  • 355
  • 3
  • 13
  • Why would you want to have the coordinates of the Button in C++? Usually you have the data model in C++, and the View in QML. The data model should be view agnostic. Further you *can* but *should not* query QML from C++. Let the QML side tell the C++ side what C++ needs to know. – derM - not here for BOT dreams Aug 22 '17 at 15:09
  • I should send it to another app. – Nikxp Aug 23 '17 at 06:44
  • A `GridView` uses dynamic instantiation, which means, you can't be sure, all `Buttons` defined in your model will be instantiated at every point in time. Further the `GridView` is a `Flickable` so the positions will change, when flicking, where you will have a lot of changes for tons of objects. How will you (conceptually) handle this? This is, because in your question you only handle *removal and addition* instead of flicking around. If it is rather static, you should consider a `Repeater` and a `Grid` instead. – derM - not here for BOT dreams Aug 23 '17 at 06:49
  • I'd like to wait when flicking, or moving end's, and will find all Buttons in hierarchical QQuickItem tree, because i sould send correct coordinates, only when they don't changed for some time. I used Grid earlier, but catch some problems with it. Is there any signal, that qml's GridView ends rebuilding? – Nikxp Aug 23 '17 at 07:30

1 Answers1

1

There is no signal for when the GridView is rebuilt

However the GridView has a property moving and the signal movementEnded

I would have each Button in your GridView connected to this signal. Further handle the Component.onCompleted of the Button. This Signal is fired when ever the Button is (re)created.

Now you expose a Q_INVOCABLE in some C++ object, that takes the required information as parameters. Let's say, its signature is

void reportPosition(QString name, int x, int y)

Now in the Button you have:

id: myGridView
delegate: Button {
    Component.onCompleted: {
        var p = mapToGlobal(x, y)
        myCppObject.reportPosition(objectname, p.x, p.y)
    }
    Connections {
        target: myGridView
        onMovementEnded: {
        var p = mapToGlobal(x, y)
        myCppObject.reportPosition(objectname, p.x, p.y)
    }
}

With this we achieved:

  • C++ gets to know the position of all created Buttons when their movement has ended
  • C++ gets to know the position of all newly created Buttons upon creation (guard it with if (!moving) [...] if you don't want the position of newly created Buttons, when they are moving)
  • You don't need to query QML from C++ but have QML report to C++

This is just an outline of the idea. I don't have the means to test it right now, so there might be errors.

  • mapToGlobal is a C++ function. I used it, but only, when i already have QQuickItem pointer on Button. As i know, there is no elegant and clear way to do it in qml (for example this solution is dirty, as author said https://stackoverflow.com/questions/21454393/qml-screen-coordinates-of-component) – Nikxp Aug 23 '17 at 13:55
  • [`mapToGlobal()`](http://doc.qt.io/qt-5/qml-qtquick-item.html#mapToGlobal-method) is a C++ function exposed to QML by every `Item` – derM - not here for BOT dreams Aug 23 '17 at 13:57
  • Of course you can also call the function and pass the Button itself to C++ if you prefer to have a object pointer. That is entirely up to you! – derM - not here for BOT dreams Aug 23 '17 at 13:58