2

How do you get the size of the QML ApplicationWindow in C++?

QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

if (engine.rootObjects().isEmpty())
    return -1;

QObject *application_object = engine.rootObjects().first();

// Throws ApplicationWindow_QMLTYPE_11::height(int), no such signal
QObject::connect(application_object, SIGNAL(height(int)), &my_obj_here, SLOT(set_game_height(int)));
QObject::connect(application_object, SIGNAL(width(int)), &my_obj_here, SLOT(set_game_width(int)));

return app.exec();

I realize that I'm also not getting the size of the contents of the ApplicationWindow (minus the toolbar, menubar etc), but how do I get access to that?

Trying to access the window property on the window_object using the property method returns a null pointer.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Ben Hoff
  • 1,058
  • 1
  • 11
  • 24

1 Answers1

2

One possible solution is to use QQmlProperty to obtain the QQuickItem, then connect with the signals heightChanged and widthChanged, these signals only notify that the property has changed but it does not indicate the value, so you must use the method height() and width().

QObject *topLevel = engine.rootObjects().first();
QQuickItem *contentItem =qvariant_cast<QQuickItem *>(QQmlProperty::read(topLevel, "contentItem"));
if(contentItem){
    QObject::connect(contentItem, &QQuickItem::heightChanged,
                     [&my_obj_here, contentItem](){
        my_obj_here.set_game_height(contentItem->height());
    });
    QObject::connect(contentItem, &QQuickItem::widthChanged, 
                     [&my_obj_here, contentItem](){
        my_obj_here.set_game_width(contentItem->width());
    });
}

Another solution is to make the connection on the QML side, for this you must create the q-property:

class GameObject: public QObject{
    Q_OBJECT
    Q_PROPERTY(int game_width READ game_width WRITE set_game_width NOTIFY game_widthChanged)
    Q_PROPERTY(int game_height READ game_height WRITE set_game_height NOTIFY game_heightChanged)
public:
    using QObject::QObject;
    int game_width() const{
        return m_width;
    }
    void set_game_width(int width){

        if(width == m_width)
            return;
        m_width = width;
        emit game_widthChanged();
    }
    int game_height() const{
        return m_height;
    }
    void set_game_height(int height){
        if(height == m_height)
            return;
        m_height = height;
        emit game_heightChanged();
    }
signals:
    void game_widthChanged();
    void game_heightChanged();
private:
    int m_width;
    int m_height;
};

main.cpp

...
GameObject my_obj_here;

QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("my_obj_here", &my_obj_here);
...

main.qml

ApplicationWindow{


    Connections{
        target: contentItem
        onHeightChanged:
            my_obj_here.game_height = height
        onWidthChanged:
            my_obj_here.game_width = width
    }
    ...
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Any reason to use qvariant_cast instead using the`QVariant::value` method? I feel like the `value` method is more readable, but I'm wondering if that's because I'm just not use to casting, and wanted to get an outside opinion. – Ben Hoff Jul 08 '18 at 09:38
  • 1
    @BenHoff they are equivalent, it is a matter of taste :) – eyllanesc Jul 08 '18 at 09:43