What exactly does FocusScope do in QML?

If you look at the documentation of FocusScope, you will see this:

Focus scopes assist in keyboard focus handling when building reusable QML components.

God I wish I could understand the entirety of FocusScope by reading this line of text. To be fair, the documentation has links to a rather elaborate article which explains how keyboard focus works in QML, and somewhere in that article FocusScope is also covered. However, honestly speaking that article will likely leave you more confused about FocusScope.

In this blog, I want to demystify keyboard focus and FocusScope, so that you can use it with utmost confidence and you know exactly what you are getting into.

Understanding Keyboard Focus

First, let’s understand keyboard focus itself. QML’s Item has a focus property, which can be set by the developer to true, and by default it’s false. When we set an Item‘s focus property to true, that item receives keyboard focus.

Here is a small piece of QML code in which we define a TextBox component for accepting a single line of text. We then create a form using several instances of this component.

import QtQuick
import QtQuick.Window

Window {
    width: 320
    height: 240
    visible: true
    title: qsTr("Understanding Keyboard Focus")
    color: "lightsteelblue"

    Grid {
        columns: 2
        spacing: 10
        anchors.centerIn: parent

        Text { text: "Name: " }
        TextBox { }

        Text { text: "Place: " }
        TextBox { }

        Text { text: "Animal: " }
        TextBox { }

        Text { text: "Thing: " }
        TextBox { }
    }

    component TextBox : Rectangle {
        width: 200
        height: textInput.implicitHeight + 8
        border {
            width: textInput.focus ? 2 : 1
            color: textInput.focus ? "black" : "gray"
        }

        TextInput {
            id: textInput
            width: parent.width - 8
            anchors.centerIn: parent
        }
    }
}

When we execute the above QML code, we see a window like this.

None of the TextBox instances already have keyboard focus, as evidenced by the fact that we don’t see a blinking cursor anywhere.

Let’s try to assign keyboard focus to the first TextBox, by setting it’s focus property to true.

Grid {
    columns: 2
    spacing: 10
    anchors.centerIn: parent

    Text { text: "Name: " }
    TextBox {
        focus: true
    }

    Text { text: "Place: " }
    TextBox { }

    Text { text: "Animal: " }
    TextBox { }

    Text { text: "Thing: " }
    TextBox { }
}

When we execute this piece of code, this is what we get.

!!! NO DIFFERENCE !!!

We don’t see a blinking cursor still. Why?

Because assigning focus to the TextBox item, caused its root Rectangle to receive focus and not the TextInput inside it. So, how do we get the TextInput inside it to get focus?

😈 What if we aliased TextBox‘s focus property to its TextInput‘s focus property? 😈

component TextBox : Rectangle {
    property alias focus: textInput.focus

    width: 200
    height: textInput.implicitHeight + 8
    border {
        width: textInput.focus ? 2 : 1
        color: textInput.focus ? "black" : "gray"
    }

    TextInput {
        id: textInput
        width: parent.width - 8
        anchors.centerIn: parent
    }
}

Well, this will cause a run-time error: 🤕

KeyboardFocus.qml:32:9: Cannot override FINAL property

Alright, let’s try and do this then. 😈 Whenever the Rectangle gets focus, let’s have TextInput‘s focus copy it. 😈

component TextBox : Rectangle {
    width: 200
    height: textInput.implicitHeight + 8
    border {
        width: textInput.focus ? 2 : 1
        color: textInput.focus ? "black" : "gray"
    }

    TextInput {
        id: textInput
        width: parent.width - 8
        anchors.centerIn: parent
        focus: parent.focus
    }
}

When we execute the program, we will see that the first TextBox did get focus …

… but we see a warning on the console! 🤕

KeyboardFocus.qml:39:9: QML TextInput: Binding loop detected for property "focus"

Why? 🙁

  • When Rectangle‘s focus becomes true, it causes TextInput‘s focus to become true.
  • Which then causes Rectangle‘s focus to become false, which will cause TextInput‘s focus to become false —- ergo, binding loop!

So, clearly this is not a good idea.

Now, back to our problem statement. How do I get TextInput to get focus when TextBox gets focus, without causing all these binding loop problems? 😫

Enter FocusScope

On the one hand FocusScope is exactly like Item. It can be placed and sized like any Item. It can also be anchored exactly like an Item, and it has no visual appearance, exactly like Item which has no visual appearance either. But that’s where the similarities end. What a FocusScope actually does is, it forwards any focus it receives to that one child item within it whose focus property was hard-coded to true.

FocusScope is like a proxy. Veteran QtWidgets users would have used QLabel::setBuddy() to forward focus from a QLabel to any QWidget next to it. That’s kind of what FocusScope does. I would have actually preferred the item to be called FocusProxy (or even FocusBuddy) because that’s exactly what it does. As a QML developer, you can package a complex component inside a FocusScope, in which one of the child items has its focus property set to true. The item whose focus property is set to true will receive focus, when the root FocusProxy receives keyboard focus.

component TextBox : FocusScope {
    width: 200
    height: textInput.implicitHeight + 8

    Rectangle {
        id: background
        anchors.fill: parent
        border {
            width: textInput.focus ? 2 : 1
            color: textInput.focus ? "black" : "gray"
        }

        TextInput {
            id: textInput
            width: parent.width - 8
            anchors.centerIn: parent

            // We mark this TextInput as the item
           // which is supposed to get focus when
           // the FocusScope of the TextBox gets
           // focus.
            focus: true
        }
    }
}

Said in other words, FocusScope receives focus only to forward it to that one child item within it whose focus property was set to true.

Now, when we run the application we will see that the first TextBox actually received keyboard focus, because it has a blinking cursor ….

… but all the TextBoxes have thick borders !!!!

Wait a minute. Let’s go back that code where we determine the border thickness.

component TextBox : FocusScope {
    width: 200
    height: textInput.implicitHeight + 8

    Rectangle {
        id: background
        anchors.fill: parent
        border {
            // Border is thick and black,
           // if textInput has focus=true
            width: textInput.focus ? 2 : 1
            color: textInput.focus ? "black" : "gray"
        }

        TextInput {
            id: textInput
            width: parent.width - 8
            anchors.centerIn: parent
            focus: true
        }
    }
}

Clearly all the four TextInput instances within the four TextBox items have their focus property set to true.

Look ma, many items seem to have focus!!!

Shouldn’t only one item have focus?

Yes, only one item actually has keyboard focus. Really, pinky swear. Believe me. I am telling the truth. 🤓

But within a FocusScope, its possible for an item can have its focus property set to true, without it actually having focus. 🤨

Let’s demystify this. Take a look at this code:

component ThickRectangle : Item {
    width: 80; height: 80

    Rectangle {
        anchors.fill: parent
        border { width: focus ? 4 : 1; color: "black" }
        focus: true 
    }
}

Grid {
    columns: 2
    spacing: 5

    ThickRectangle { }
    ThickRectangle { }
    ThickRectangle { }
    ThickRectangle { }
}

We are defining a component called ThickRectangle whose border width becomes “thick” when it has keyboard focus. We then place 4 of these within a Grid positioner. Notice that the Rectangle item within ThickRectangle component requests for focus upon creation. When we execute this program, we will see ….

… only the first rectangle actually receiving focus. This means that the focus property value on other rectangles became false. We can now relax, QML engine is working fine. Only one of the items actually got focus and actually has focus property set to true, even though many had set their focus property to true in code. So far, so good.

The QML engine assigns focus to the first item that requested for focus, which consequently causes focus on all other items to become false, even though it was initialised as true in code.

Now, let’s change one small thing in the code.

component ThickRectangle : FocusScope {
    width: 80; height: 80

    Rectangle {
        anchors.fill: parent
        border { width: focus ? 4 : 1; color: "black" }
        focus: true
    }
}

Grid {
    columns: 2
    spacing: 5
    anchors.centerIn: parent

    ThickRectangle { }
    ThickRectangle { }
    ThickRectangle { focus: true }
    ThickRectangle { }
}

Notice that the root item of ThickRectangle component is now a FocusScope, instead of Item. And, we are setting focus of the third instance of ThickRectangle to true. This time, when we run the program we will see ….

… all Rectangles within ThickRectangle instances have their focus property set to true. But I promise, only the third item really really really has focus.

You see, the value of focus property in an item within a FocusScope is not used to signify which item has focus, but it is rather used to signify which item should get focus whenever the FocusScope receives focus.

For that reason, within a FocusScope it’s best to make use of Item.activeFocus to test if an item really has focus. Item.activeFocus is a read-only property, which will become true when an item has “active focus” (or real focus). This property is set by the underlying runtime and is always a dependable source of truth regarding keyboard focus, even within a FocusScope. So, let’s use this in addition to focus in our code.

component ThickRectangle : FocusScope {
    width: 80; height: 80

    Rectangle {
        anchors.fill: parent
        border { width: focus ? 4 : 1; color: "black" }
        color: activeFocus ? "lightsteelblue" : "white"
        focus: true
    }
}

Grid {
    columns: 2
    spacing: 5
    anchors.centerIn: parent

    ThickRectangle { }
    ThickRectangle { }
    ThickRectangle { focus: true }
    ThickRectangle { }
}

In this code, while border thickness is determined by focus, fill color is determined by activeFocus. Now, when we run the code we will see ….

… all rectangles continue to have thick borders, but only the third item (the one with real focus) has lightsteelblue fill color. See, I told you so!

So, moral of the story is: within a FocusScope, always use activeFocus to determine who has real focus.

Okay, coming back to our TextBox example. Let’s use activeFocus to provide thick border on our Rectangle now.

component TextBox : FocusScope {
    width: 200
    height: textInput.implicitHeight + 8

    Rectangle {
        id: background
        anchors.fill: parent
        border {
            width: textInput.activeFocus ? 2 : 1
            color: textInput.activeFocus ? "black" : "gray"
        }

        TextInput {
            id: textInput
            width: parent.width - 8
            anchors.centerIn: parent
            focus: true
        }
    }
}

Grid {
    columns: 2
    spacing: 10
    anchors.centerIn: parent

    Text { text: "Name: " }
    TextBox { }

    Text { text: "Place: " }
    TextBox { }

    Text { text: "Animal: " }
    TextBox { focus: true }

    Text { text: "Thing: " }
    TextBox { }
}

Now, when I run the program I will see that only the TextBox I set focus to will have keyboard focus.

Now, we are getting somewhere. Isn’t it?

In summary: FocusScope forwards keyboard focus to a specific child item within it. Said in other words, FocusScope behaves like a proxy for receiving keyboard focus into a specific child item.

What if we have FocusScope within FocusScope?

Consider this code:

component Form : FocusScope {
    width: formLayout.width
    height: formLayout.height

    Grid {
        id: formLayout
        columns: 2
        spacing: 10

        Text { text: "Name: " }
        TextBox { }

        Text { text: "Place: " }
        TextBox { }

        Text { text: "Animal: " }
        TextBox { focus: true }

        Text { text: "Thing: " }
        TextBox { }
    }
}

component TextBox : FocusScope {
    width: 200
    height: textInput.implicitHeight + 8

    Rectangle {
        id: background
        anchors.fill: parent
        border {
            width: textInput.activeFocus ? 2 : 1
            color: textInput.activeFocus ? "black" : "gray"
        }

        TextInput {
            id: textInput
            width: parent.width - 8
            anchors.centerIn: parent
            focus: true
        }
    }
}

Here, we notice

  • TextBox is a FocusScope which forwards focus to the TextInput item inside it.
  • Form is a FocusScope which forwards focus to the third TextBox inside it.

Now, when we create an instance of the Form item like this …

Form { }

… none of the fields will actually get focus, because the Form item (which is a FocusScope) doesn’t have “real focus” (or activeFocus). However, the third TextBox‘s focus property will be true and within that the TextInput item’s focus will be true. That’s okay, because like I said before the meaning of focus property within a FocusScope is different. It only signifies which item will receive focus, should the FocusScope actually get focus. If the FocusScope itself doesn’t have focus, then none of the items have focus anyway.

But when I set focus on the Form

Form { focus: true }

… the FocusScope which the form is forwards focus to the third TextBox, which is another FocusScope that forwards focus to the TextInput within it. And we get exactly what we were hoping to get:

FocusScope is a proxy for a child-item’s focus, and if that child-item is a FocusScope then it will proxy for its child-item and so on, until an actual item receives keyboard focus. Clear now?

In all honesty, this wouldn’t have been so damn confusing if it was called FocusProxy instead of FocusScope.

Delayed Loading Of Delegates in QML Views

In your QML code, you will encounter times when you will have to execute something slightly later. Qt offers a method called Qt.callLater(), using which you can schedule a function for later execution. Additionally, it also ensures that multiple calls to the same function are batched into a single call. This is really very useful in QML code. Let’s look a very simple use-case:

Rectangle {
    // ....
    
    onWidthChanged: Qt.callLater(sizeGotChanged)
    onHeightChanged: Qt.callLater(sizeGotChanged)

    function sizeGotChanged() {
        // This function gets called whenever width
        // or height changes.
    }

    // ....
}

Here, the function sizeGotChanged() gets called whenever either width or height changes for whatever reason. If they both get changed back to back, then sizeGotChanged() is callLater()‘ed twice, but this will result in a single call to sizeGotChanged() at some point in the very near future.

I routinely use this mechanism to delay loading of heavy delegates in ListViews. For example, consider that we have a ListView which hooks up to a model and makes use of heavy delegates. By heavy, I mean a delegate that takes considerable amount of time (30ms+) to instantiate. Such delegates cause scrolling in ListView to get slow and thereby makes the view sluggish to use. Instead of loading the whole delegate, we could load only critical parts of the delegate upon instantiation and load non-critical parts later. For example:

ListView {
    // ....

    model: myModel
    delegate: myDelegate

    // ...
}

Component {
    id: myDelegate 

    Item {
        id: lightPart
        // ...

        Loader {
            active: false
            anchors.fill: parent
            sourceComponent: Item {
                id: heavyPart
                // ...
            }
            
            function initialize() { active = true }
            Component.onCompleted: Qt.callLater(initialize)

            // ....
        }

        // ...
    }
}

In the code snippet above, you can see how the delegate is broken down into light and heavy parts. The light part is loaded instantly, whereas the heavy part is loaded later by a Loader item. This is accomplished by calling later the initialize() method in the Loader, which basically sets active to true.

This works great for the most part, until you realize that this causes heavy part of the delegates to get loaded when users are not scrolling the ListView as fast as callLater() is calling the initialize() method. To address this, you may want to delay call to the initialize() method by 100ms for instance. During that time if the delegate scrolls into view and scrolls out, the heavy part is not loaded. To keep the user from getting perplexed about empty looking delegates, we could load a place holder image for those 100ms while the user is busy scrolling rapidly. This is a common technique used by many web-apps and even desktop apps.

Scrite uses place holder images to render scenes in a screenplay, while user is rapidly scrolling. Watch this video to know more: “Closing the Gaps – QML on Desktop” – Qt Developer Conference (qtdevcon.com)

In such cases, Qt.callLater() is insufficient because it does not allow us to to specify how much later we want a method to be called. One way to address this would be to use a Timer.

ListView {
    // ....

    model: myModel
    delegate: myDelegate

    // ...
}

Component {
    id: myDelegate 

    Item {
        id: lightPart
        // ...

        Loader {
            id: heavyPartLoader
            anchors.fill: parent
            active: false
            sourceComponent: Item {
                id: heavyPart
                // ...
            }

            Timer {
                interval: 100
                running: true
                repeating: false
                onTriggered: heavyPartLoader.active = true
            }

            // ....
        }

        // ...
    }
}

While this works, the one issue with this approach is that we have a Timer object for each delegate instance, which has no purpose once the initial 100ms have passed and the heavy part of the delegate is loaded.

Instead of creating Timer objects statically like we did here, lets create them dynamically so that they auto-destroy themselves once they invoke the required callback.

/ Filename: utils.js
function execLater(contextObject, delay, callback, args) {
    var timer = Qt.createQmlObject("import QtQml 2.15; Timer { }", contextObject);
    timer.interval = delay === undefined ? 100 : delay
    timer.repeat = false
    timer.triggered.connect(() => {
                                callback(args)
                                timer.destroy()
                            })
    timer.start()
}

The execLater() method in this JavaScript code creates a Timer item, which self-destroys after invoking a callback upon timeout. The Timer item is created as a child of contextObject, which means that if for some reason the contextObject gets destroyed before the timeout duration, the Timer object itself gets destroyed.

Now in our QML code, we import this code into a name space and call the execLater() method. We also show a place holder image until the heavy part is actually loaded.

import "utils.js" as Utils

Component {
    id: myDelegate 

    Item {
        id: lightPart
        // ...

        Loader {
            id: heavyPartLoader
            anchors.fill: parent
            active: false
            sourceComponent: Item {
                id: heavyPart
                // ...
            }

            function initialize() { active = true }
            Component.onCompleted: {
                Utils.execLater(heavyPartLoader, 100, initialize)
            }

            Image {
                id: placeHolderImage
                anchors.fill: parent
                visible: parent.status !== Loader.Ready
                // ...
            }

            // ....
        }

        // ...
    }
}

This approach solves three problems

  1. We get to schedule call to a function a stated amount of time later, in this case 100 ms.
  2. We get to delete from memory the Timer object once its purpose is served.
  3. Until the heavy part of the delegate is loaded, we get to show a place holder image, letting the user know that some content is coming.

However, multiple calls to initialize() from Utils.execLater() won’t get batched into a single call to initialize(), like it does in Qt.callLater().

Additionally if you observe carefully, we have unwittingly thrown Loader and Image objects into memory, for each instance of the delegate. These objects are not needed once the heavy part is loaded. We will now need to further refactor our code to eliminate these objects.

import "utils.js" as Utils

Component {
    id: myDelegate 

    Item {
        id: lightPart
        // ...

        property Item placeHolderItem    
        Component.onCompleted: {
            placeHolderItem = placeHolderImageComponent.createObject(lightPart)
            Utils.execLater(lightPart, 100, loadHeavyPart)
        }

        property Item heavyPartItem
        function loadHeavyPart() {
            heavyPartItem = heavyPartComponent.createObject(lightPart)
            placeHolderItem.destroy()
        }

        // ...
    }
}

Component {
    id: heavyPartComponent

    Item {
        anchors.fill: parent
        // ...
    }
}

Component {
    id: placeHolderImageComponent

    Image {
        anchors.fill: parent
        // ...
    }
}

Here, you can notice that we have created the place holder image dynamically, which means we can destroy it once its purpose is served. You can also notice how we create the heavy part dynamically without using Loader.

The code below brings all of these concepts together into a working example:

// File: utils.js
function execLater(contextObject, delay, callback, args) {
    var timer = Qt.createQmlObject("import QtQml 2.15; Timer { }", contextObject);
    timer.interval = delay === undefined ? 100 : delay
    timer.repeat = false
    timer.triggered.connect(() => {
                                callback(args)
                                timer.destroy()
                            })
    timer.start()
}

function boundRandom(min, max) {
    return min + Math.random() * (max-min)
}

// File: example.qml
import QtQuick
import QtQuick.Window
import QtQuick.Controls
import "utils.js" as Utils

Window {
    width: 640
    height: 480
    visible: true

    ListView {
        id: myView
        anchors.fill: parent
        model: 300
        delegate: myDelegate
        ScrollBar.vertical: ScrollBar { }
    }

    Component {
        id: myDelegate

        Item {
            id: lightPart
            width: myView.width
            height: Utils.boundRandom(50, 300)

            required property int index

            property Item placeHolderItem
            Component.onCompleted: {
                placeHolderItem = 
                  placeHolderComponent.createObject(lightPart, {"index": index})
                Utils.execLater(lightPart, 1000, loadHeavyPart)
            }

            property Item heavyPartItem
            function loadHeavyPart() {
                heavyPartItem = 
                  heavyPartComponent.createObject(lightPart, {"index": index})
                placeHolderItem.destroy()
            }
        }
    }

    Component {
        id: heavyPartComponent

        Rectangle {
            required property int index

            anchors.fill: parent
            color: Qt.rgba( Utils.boundRandom(0.6,0.9),
                            Utils.boundRandom(0.6,0.9),
                            Utils.boundRandom(0.6,0.9), 1)

            Text {
                anchors.centerIn: parent
                text: "Heavy Part: " + index
                font.pixelSize: 18
            }
        }
    }

    Component {
        id: placeHolderComponent

        Rectangle {
            required property int index

            anchors.fill: parent
            color: Qt.rgba( Utils.boundRandom(0.6,0.9),
                            Utils.boundRandom(0.6,0.9),
                            Utils.boundRandom(0.6,0.9), 0.3)

            Text {
                anchors.centerIn: parent
                text: "Placeholder: " + index
                font.pixelSize: 18
            }
        }
    }
}

Leveraging shadow maps in Qt, without using QOpenGLFrameBufferObject

A few years ago I was attempting to use shadow maps in Qt/OpenGL but was simply unable to use QOpenGLFrameBufferObject as a shadow-buffer. I had even posted a question about it on stack-overflow here. It turns out, you cannot use QOpenGLFrameBufferObject for creating shadow buffers. So, I had to resort to native OpenGL calls. Recently someone reached to me on LinkedIn asking me if I could share the code.

So here it is: https://github.com/pnudupa/codesamples/tree/master/bike_shadows

When the code at this repository is compiled and executed, we can see a window with two bikes, with their shadows on the ground and on each other.

You can press any key to rotate the whole scene and watch the shadows move.

QObjectFactory

Factory Design Pattern is a well known pattern. Its a way to organise code so that class-instances can be created at run time against a developer defined key. Factories specialise in create objects of a specific type. For example (yes, this example is inspired from the example on the Wikipedia page about Factory Design Patterns)

#define interface class
#define implements : public

interface IPerson
{
public:
    virtual std::string getType() = 0;
};

class VillagePerson implements IPerson
{
public:
    virtual std::string getType() { return "VillagePerson"; }
};

class TownPerson implements IPerson
{
public:
    virtual std::string getType() { return "TownPerson"; }
};

class CityPerson implements IPerson
{
public:
    virtual std::string getType() { return "CityPerson"; }
};

class PersonFactory
{
public:
    IPerson *createPerson(const std::string &type) {
        if(type == "VillagePerson")
            return new VillagePerson;
        if(type == "TownPerson")
            return new TownPerson;
        if(type == "CityPerson")
            return new CityPerson;
        return nullptr;
    }
};

So, we can now create instances of IPerson using the PersonFactory class. For example:

PersonFactory factory;
IPerson *person = factory.createPerson("CityPerson");

Now person will point to an instance of CityPerson class. Thats the whole point of a factory, to create object instances based on a key. In this case the key was type name as string.

Qt uses Factory Design Pattern in several places. For example the QItemEditorFactory class helps create editor widgets for items in a QAbstractItemView. Over there the type is integer. There is also a QStyleFactory that creates instances of QStyle based on style-name as key.

Almost every software project that I have been a part of makes use of the factory design pattern. Almost all of the factory classes I have written create QObject subclasses based on a QString or QByteArray key. Typically the key is name of the QObject subclass, but its not always the case. After one writes enough number of factories, it becomes boring to write the same thing over and over again. So I came up with a simple solution.

QObjectFactory class

Lets take the same example as before. Suppose we wanted to create a Person factory class. Lets also suppose that we can make peace with the fact that objects created by our factory will be QObject subclasses. So the person interface and subclasses would look like this

class AbstractPerson : public QObject
{
    Q_OBJECT

public:
    AbstractPerson(QObject *parent=nullptr)
        : QObject(parent) { }
    ~AbstractPerson() { }

    virtual QByteArray getType() const = 0;
};

class VillagePerson : public AbstractPerson
{
    Q_OBJECT

public:
    Q_INVOKABLE VillagePerson(QObject *parent=nullptr)
        : AbstractPerson(parent) { }
    ~VillagePerson() { }

    virtual QByteArray getType() const {
        return "VillagePerson";
    }
};

class TownPerson : public AbstractPerson
{
    Q_OBJECT

public:
    Q_INVOKABLE TownPerson(QObject *parent=nullptr)
        : AbstractPerson(parent) { }
    ~TownPerson() { }

    virtual QByteArray getType() const {
        return "VillagePerson";
    }
};

Notice the following

  • AbstractPerson is subclassed from QObject
  • AbstractPerson and all its subclasses have Q_OBJECT macro declared in them
  • AbstractPerson and all its subclasses have a constructor that accepts a parent pointer.
  • Subclasses of AbstractPerson have their constructor marked as Q_INVOKABLE

Now, lets register subclasses of AbstractPerson in a factory.

QObjectFactory factory;
factory.addClass<VillagePerson>();
factory.addClass<TownPerson>();
factory.addClass<CityPerson>();

That’s it. Creation of instances from the factory would be as simple as

AbstractPerson *person = factory.create<AbstractPerson>("CityPerson");

Seems magical right? Let’s look at how the QObjectFactory class is written.

class QObjectFactory
{
public:
    QObjectFactory() { }
    ~QObjectFactory() { }

    void add(const QMetaObject *mo) { m_metaObjects += mo; }
    void remove(const QMetaObject *mo) { m_metaObjects -= mo; }

    template <class T>
    void addClass() { this->add( &T::staticMetaObject ); }

    template <class T>
    void removeClass() { this->remove( &T::staticMetaObject ); }

    const QMetaObject *find(const QByteArray &className) const {
        Q_FOREACH(const QMetaObject *mo, m_metaObjects) {
            if( !qstrcmp(className.data(), mo->className()) )
                return mo;
        }
        return nullptr;
    }

    QObject *create(const QByteArray &className, QObject *parent=nullptr) const {
        const QMetaObject *mo = this->find(className);
        if(mo == nullptr)
            return nullptr;
        QObject *obj = mo->newInstance(Q_ARG(QObject*,parent));
        return obj;
    }

    template <class T>
    T *create(const QByteArray &className, QObject *parent=nullptr) const {
        QObject *obj = this->create(className, parent);
        return qobject_cast<T*>(obj);
    }

private:
    QSet<const QMetaObject*> m_metaObjects;
};

Qt’s QMetaObject class provides a newInstance() method that helps us call the constructor of its QObject class using a transparent API. By using some really simple template constructs, we make the QObjectFactory class look magical.

Can we use QObjectFactory for creating widgets?

QWidget and subclasses accept a QWidget* as parent pointer, instead of QObject*. So, the QObjectFactory class in its current incarnation cannot be used as a QWidget factory. We will need to write a QWidgetFactory class, that does pretty much the same thing, just that the parent pointer will be of type QWidget*. Or, we can do something smarter.

template <class T>
class QtFactory
{
public:
    QtFactory() { }
    ~QtFactory() { }

    void add(const QMetaObject *mo) { m_metaObjects += mo; }
    void remove(const QMetaObject *mo) { m_metaObjects -= mo; }

    template <class Class>
    void addClass() { this->add( &Class::staticMetaObject ); }

    template <class Class>
    void removeClass() { this->remove( &Class::staticMetaObject ); }

    const QMetaObject *find(const QByteArray &className) const {
        Q_FOREACH(const QMetaObject *mo, m_metaObjects) {
            if( !qstrcmp(className.data(), mo->className()) )
                return mo;
        }
        return nullptr;
    }

    T *create(const QByteArray &className, T *parent=nullptr) const {
        const QMetaObject *mo = this->find(className);
        if(mo == nullptr)
            return nullptr;

        const char *t = this->type();
        QObject *obj = qobject_cast<T*>(mo->newInstance( QArgument<T*>(t,parent) ));
        return qobject_cast<T*>(obj);
    }

    template <class Class>
    Class *create(const QByteArray &className, T *parent=nullptr) const {
        T *obj = this->create(className, parent);
        return qobject_cast<Class*>(obj);
    }

private:
    const char *type() const {
        static const char *qobjectstar = "QObject*";
        static const char *qwidgetstar = "QWidget*";
        if( typeid(T) == typeid(QWidget) )
            return qwidgetstar;
        return qobjectstar;
    }

private:
    QSet<const QMetaObject*> m_metaObjects;
};

typedef QtFactory<QObject> QObjectFactory;
typedef QtFactory<QWidget> QWidgetFactory;

Notice how QtFactory is now a generic template class and we create QObjectFactory and QWidgetFactory from it. Now we can use QWidgetFactory as follows

class LineEdit : public QLineEdit
{
    Q_OBJECT

public:
    Q_INVOKABLE LineEdit(QWidget *parent=nullptr)
        : QLineEdit(parent) { }
    ~LineEdit() { }
};

class PushButton : public QPushButton
{
    Q_OBJECT

public:
    Q_INVOKABLE PushButton(QWidget *parent=nullptr)
        : QPushButton(parent) {
        this->setText("Button");
    }
    ~PushButton() { }
};

int main(int argc, char **argv)
{
    QApplication a(argc, argv);

    QWidgetFactory factory;
    factory.addClass<LineEdit>();
    factory.addClass<PushButton>();

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);

    layout->addWidget(factory.create("LineEdit", &window));
    layout->addWidget(factory.create("PushButton", &window));

    window.show();

    return a.exec();
}

How about key as something other than class name?

So far we are using class-name as the lookup key in the factory class. What if we wanted to use as key something other class-names? For example, we may want a widget-factory that helps us create widgets based on the type of data we want to edit using it. We can make use of Q_CLASSINFO() to add additional data about the widget class into its QMetaObject as follows.

class LineEdit : public QLineEdit
{
    Q_OBJECT
    Q_CLASSINFO("DataTypes", "QString;QUrl")

public:
    Q_INVOKABLE LineEdit(QWidget *parent=nullptr)
        : QLineEdit(parent) { }
    ~LineEdit() { }
};

class CheckBox : public QCheckBox
{
    Q_OBJECT
    Q_CLASSINFO("DataTypes", "bool")

public:
    Q_INVOKABLE CheckBox(QWidget *parent=nullptr)
        : QCheckBox(parent) {
        this->setText("Yes/No");
    }
    ~CheckBox() { }
};

Now, we update the QtFactory class to lookup based on the semi-colon separated list in value to DataTypes Q_CLASSINFO.

template <class T>
class QtFactory
{
public:
    QtFactory(const QByteArray &key=QByteArray()) : m_classInfoKey(key) { }
    ~QtFactory() { }

    QByteArray classInfoKey() const { return m_classInfoKey; }

    void add(const QMetaObject *mo) {
        QList<QByteArray> keys;
        const int ciIndex = mo->indexOfClassInfo(m_classInfoKey.constData());
        if(ciIndex >= 0) {
            const QMetaClassInfo ci = mo->classInfo(ciIndex);
            keys = QByteArray(ci.value()).split(';');
        }
        keys.append( QByteArray(mo->className()) );
        m_metaObjects.insert(mo, keys);
        Q_FOREACH(QByteArray key, keys)
            m_keyMap[key].append(mo);
    }

    void remove(const QMetaObject *mo) {
        const QList<QByteArray> keys = m_metaObjects.take(mo);
        Q_FOREACH(QByteArray key, keys) {
            QList<const QMetaObject *> mos = m_keyMap.take(key);
            mos.removeOne(mo);
            if(mos.isEmpty())
                continue;
            m_keyMap[key] = mos;
        }
    }

    // ...

    QList<QByteArray> keys() const { return m_keyMap.keys(); }

    const QMetaObject *find(const QByteArray &val) const {
        const QList<const QMetaObject *> mos = m_keyMap.value(val);
        return mos.isEmpty() ? nullptr : mos.last();
    }

    // ...

private:
    QMap<const QMetaObject*, QList<QByteArray> > m_metaObjects;
    QMap<QByteArray, QList<const QMetaObject *> > m_keyMap;
    QByteArray m_classInfoKey;
};

Notice how the factory class now uses both class-names and Q_CLASSINFO data to lookup which class to create an instance of.

Now we can use the QWidgetFactory class as follows.

int main(int argc, char **argv)
{
    QApplication a(argc, argv);

    QWidgetFactory factory("DataTypes");
    factory.addClass<LineEdit>();
    factory.addClass<CheckBox>();

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);

    layout->addWidget(factory.create("QString", &window));
    layout->addWidget(factory.create("QUrl", &window));
    layout->addWidget(factory.create("bool", &window));

    window.show();

    return a.exec();
}

The entire widget factory is just a header file. You can expand this block to view/copy the entire code.

QtFactory Source Code
/****************************************************************************
**
** Copyright (C) Prashanth Udupa, Bengaluru
** Email: prashanth.udupa@gmail.com
**
** This code is distributed under LGPL v3. Complete text of the license
** can be found here: https://www.gnu.org/licenses/lgpl-3.0.en.html
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/

#ifndef QOBJECTFACTORY_H
#define QOBJECTFACTORY_H

#include <QSet>
#include <QMap>
#include <QWidget>
#include <QObject>
#include <QMetaObject>
#include <QMetaClassInfo>

template <class T>
class QtFactory
{
public:
    QtFactory(const QByteArray &key=QByteArray()) : m_classInfoKey(key) { }
    ~QtFactory() { }

    QByteArray classInfoKey() const { return m_classInfoKey; }

    void add(const QMetaObject *mo) {
        QList<QByteArray> keys;
        const int ciIndex = mo->indexOfClassInfo(m_classInfoKey.constData());
        if(ciIndex >= 0) {
            const QMetaClassInfo ci = mo->classInfo(ciIndex);
            keys = QByteArray(ci.value()).split(';');
        }
        keys.append( QByteArray(mo->className()) );
        m_metaObjects.insert(mo, keys);
        Q_FOREACH(QByteArray key, keys)
            m_keyMap[key].append(mo);
    }
    void remove(const QMetaObject *mo) {
        const QList<QByteArray> keys = m_metaObjects.take(mo);
        Q_FOREACH(QByteArray key, keys) {
            QList<const QMetaObject *> mos = m_keyMap.take(key);
            mos.removeOne(mo);
            if(mos.isEmpty())
                continue;
            m_keyMap[key] = mos;
        }
    }

    template <class Class>
    void addClass() { this->add( &Class::staticMetaObject ); }

    template <class Class>
    void removeClass() { this->remove( &Class::staticMetaObject ); }

    QList<QByteArray> keys() const { return m_keyMap.keys(); }

    const QMetaObject *find(const QByteArray &val) const {
        const QList<const QMetaObject *> mos = m_keyMap.value(val);
        return mos.isEmpty() ? nullptr : mos.last();
    }

    T *create(const QByteArray &className, T *parent=nullptr) const {
        const QMetaObject *mo = this->find(className);
        if(mo == nullptr)
            return nullptr;
        const char *t = this->type();
        QObject *obj = qobject_cast<T*>(mo->newInstance( QArgument<T*>(t,parent) ));
        return qobject_cast<T*>(obj);
    }

    template <class Class>
    Class *create(const QByteArray &className, T *parent=nullptr) const {
        T *obj = this->create(className, parent);
        return qobject_cast<Class*>(obj);
    }

private:
    const char *type() const {
        static const char *qobjectstar = "QObject*";
        static const char *qwidgetstar = "QWidget*";
        if( typeid(T) == typeid(QWidget) )
            return qwidgetstar;
        return qobjectstar;
    }

private:
    QMap<const QMetaObject*, QList<QByteArray> > m_metaObjects;
    QMap<QByteArray, QList<const QMetaObject *> > m_keyMap;
    QByteArray m_classInfoKey;
};

typedef QtFactory<QObject> QObjectFactory;
typedef QtFactory<QWidget> QWidgetFactory;

#endif // QOBJECTFACTORY_H

Anchor Layout for Widgets

I love QML. It’s a software developer’s ticket to build truly amazing user interfaces while at the same time not compromising on software architecture. Its simply fantastic!

One of the features of QML UI that I love the most is Anchor Layouts. Coming from the widgets world I knew QVBoxLayout, QHBoxLayout, QGridLayout and QFormLayout. These layouts help place and resize contents of a widget in a predefined fashion. They were the perfect set of layouting tools until I discovered Anchor Layouts. Now, whenever I have to go back to writing widgets UI; I feel that lack of Anchor Layouts in Widgets world more than ever. I have gotten used to placing one UI element to the right-of, left-of, above, below of another UI element and so on. I like being able to say that this UI element should be as wide as the other element, but placed on top. You can’t do that with widgets as straight-forwardly as you can do it in QML. So, I decided to build an AnchorLayout class for use with QtWidgets. This blog post is all about that.

For the uninformed: what is an Anchor Layout?

Qt’s layout classes QBoxLayout, QGridLayout and QFormLayout distributes space available in a container widget among its child widgets using some logic. Anchor Layouts on the other hand think of a container and its contents as a UI elements with each of them having invisible anchor lines as follows

We then setup UI elements such that one UI element’s anchor-line is “anchored” to another UI element’s anchor-line. Of-course, this works as long as the UI elements in question are either siblings OR share a container-contained relationship.

In addition to being able to “anchor” lines on each other, we can also establish a space between them, by specifying a margin. When we anchor one item on another, we can in addition to that also say that we need a margin. That way we can introduce space between UI elements.

For example: we could say, anchor the left of blue UI element to the right of a red UI element.

We could further say that while we want the left of the blue UI element to stand to the right of the red UI element, we want a gap of 10 pixels between them.

The way we think anchor-layouts is distinct from the way we think QLayouts. When we think “anchor-layouts” we think pretty much like how we would think when we arrange objects on our desk. Place one item to the right of the other, top of the other OR place this item to the extreme right of the table, that one to the extreme left and so on.

Anchor Layouts are more natural to think than traditional QLayouts. That is not to say that traditional layouts are bad. Having an option to use both is better.

I have implemented an AnchorLayout class that offers this functionality. If you just want to download and use the code, git-pull a copy of the code from here: https://github.com/pnudupa/anchorlayout

Simple Example

First let’s look at the results. Suppose I wanted to place a QFrame within a QWidget such that it would occupy the entire container, by leaving behind some margin.

int main(int argc, char **argv)
{
    QApplication a(argc, argv);

    QWidget container;

    QFrame *frame = new QFrame(&container);
    frame->setFrameStyle(QFrame::Box);

    AnchorLayout *containerLayout = AnchorLayout::get(&container);
    AnchorLayout *frameLayout = AnchorLayout::get(frame);
    frameLayout->fill(containerLayout)->setMargins(50);

    container.resize(400, 400);
    container.show();

    return a.exec();
}

When executed, we will get an output like this.

Surely this can be accomplished using a QVBoxLayout or QHBoxLayout as well. We are not competing with existing layouts. Only trying to bring the power of Anchor Layouts in QML to the QtWidgets world.

Show the frame in the bottom right quadrant

Suppose we wanted to show the frame in the bottom right quadrant of the container leaving a 20 pixel margin around, like this.

This is of course possible with QGridLayout, but somehow getting the placement right will be an issue. We will have to play around with sizeHint(), sizePolicy() of the frame effectively to achieve this result. You see, we want the frame to be in the bottom right quadrant, leaving a 20 pixel margin around even when the widget is resized.

With the AnchorLayout class, it is as simple as this. Notice how we borrow the anchor-lines concept from QML into this.

int main(int argc, char **argv)
{
    QApplication a(argc, argv);

    QWidget container;

    QFrame *frame = new QFrame(&container);
    frame->setFrameStyle(QFrame::Box);

    AnchorLayout *containerLayout = AnchorLayout::get(&container);
    AnchorLayout *frameLayout = AnchorLayout::get(frame);

    frameLayout->left()
               ->anchorTo(containerLayout->horizontalCenter())
               ->setMargin(20);
    frameLayout->top()
               ->anchorTo(containerLayout->verticalCenter())
               ->setMargin(20);
    frameLayout->right()
               ->anchorTo(containerLayout->right())
               ->setMargin(20);
    frameLayout->bottom()
               ->anchorTo(containerLayout->bottom())
               ->setMargin(20);

    container.resize(400, 400);
    container.show();

    return a.exec();
}

Each AnchorLayout instance has left(), right(), top(), bottom(), horizontalCenter() and verticalCenter() AnchorLines. These lines can be made to coincide with AnchorLines of other layouts.

Placing widgets in a container is simply a matter of anchoring their anchor-lines of their anchor-layouts with each other. As the anchor lines move, they take the edges of the widgets they represent with them. This way the pull-and-push of anchor lines effectively places and resizes the widgets.

Place two frames in the center, separated by a space

Suppose wanted to place two frames next to each other, in the center of a container such that

  • The width of each frame is 35% of the width of the container
  • The height of each frame is 50% of the height of the container

Like this:

Once again, the idea is to ensure that width and height ratios vis-a-vis the container must remain consistent when the container is resized.

Here is how we would use the AnchorLayout class to make this happen.

int main(int argc, char **argv)
{
    QApplication a(argc, argv);

    QWidget container;

    QLabel *frame1 = new QLabel(&container);
    frame1->setFrameStyle(QFrame::Box);
    frame1->setText("One");
    frame1->setAlignment(Qt::AlignCenter);

    QLabel *frame2 = new QLabel(&container);
    frame2->setFrameStyle(QFrame::Box);
    frame2->setText("Two");
    frame2->setAlignment(Qt::AlignCenter);

    AnchorLayout *containerLayout = AnchorLayout::get(&container);

    AnchorLayout *frame1Layout = AnchorLayout::get(frame1);
    frame1Layout->left()
                ->anchorTo(containerLayout->customLine(Qt::Vertical,0.15))
                ->setMargin(-5);
    frame1Layout->right()
                ->anchorTo(containerLayout->horizontalCenter())
                ->setMargin(5);
    frame1Layout->top()
                ->anchorTo(containerLayout->customLine(Qt::Horizontal,0.25));
    frame1Layout->bottom()
                ->anchorTo(containerLayout->customLine(Qt::Horizontal,-0.25));

    AnchorLayout *frame2Layout = AnchorLayout::get(frame2);
    frame2Layout->right()
                ->anchorTo(containerLayout->customLine(Qt::Vertical,-0.15))
                ->setMargin(-5);
    frame2Layout->left()
                ->anchorTo(containerLayout->horizontalCenter())
                ->setMargin(5);
    frame2Layout->top()
                ->anchorTo(containerLayout->customLine(Qt::Horizontal,0.25));
    frame2Layout->bottom()
                ->anchorTo(containerLayout->customLine(Qt::Horizontal,-0.25));

    container.resize(600, 400);
    container.show();

    return a.exec();
}

Notice the use of customLine() method. In addition to left(), top(), right(), bottom(), horizontalCenter() and verticalCenter() anchor lines, we can create custom anchor lines. Anchor Lines are either horizontal or vertical lines. They show up at a particular distance from the layout’s edge. For example

  • A Qt::HorizontalLine at 0.25 distance is a horizontal line that is 25% of the width from the left of the layout.
  • A Qt::HorizontalLine at -0.25 distance is a horizontal line that is 25% of the width from the right of the layout

Like all AnchorLines, custom AnchorLines can be used to anchor another another anchor-line on it as long as the orientations match. Also note how we are able to easily introduce space in-between the frames using margins.

We want one one of the frames to stick to the top, the other to the bottom.

Suppose want to achieve this.

Notice that “one” and “two” are taller than before. They are actually 75% as tall as the container. While frame one is aligned to the top, frame two is aligned to the bottom. But note also the margin and spacing. The code for accomplishing this result is almost similar to what we have written before. I have highlighted the changes.

int main(int argc, char **argv)
{
    QApplication a(argc, argv);

    QWidget container;

    QLabel *frame1 = new QLabel(&container);
    // ....

    QLabel *frame2 = new QLabel(&container);
    // ....

    AnchorLayout *containerLayout = AnchorLayout::get(&container);

    AnchorLayout *frame1Layout = AnchorLayout::get(frame1);
    // ....    
    frame1Layout->top()
                ->anchorTo(containerLayout->top())
                ->setMargin(10);
    frame1Layout->bottom()
                ->anchorTo(containerLayout->customLine(Qt::Horizontal,-0.25))
                ->setMargin(-10);

    AnchorLayout *frame2Layout = AnchorLayout::get(frame2);
    // ....
    frame2Layout->top()
                ->anchorTo(containerLayout->customLine(Qt::Horizontal,0.25))
                ->setMargin(-10);
    frame2Layout->bottom()
                ->anchorTo(containerLayout->bottom())
                ->setMargin(10);

    // ....
}

Accomplishing something like this with traditional layouts, though possible, would be quite tricky. You have to play around with stretch factors, alignments, size hints and policies. Anchor Layout just makes all this very straight forward.

Typical Application UI

A typical application UI consists of a central document area, surrounded by other widgets.

Although a main-window does indeed provide us with this construct, lets look at how we can construct such a layout by ourselves using AnchorsLayout.

Firstly, let us spell out the ratio, proportions and fixed sizes of each area

  • The menu-bar area is always along the top, occupying the full width of the window. It has a fixed height of 30 pixels.
  • The status-bar-area is always along the bottom, occupying the full width of the window. It also has a fixed height of 30 pixels.
  • The tool-box and config-box areas are to the left and right; occupying roughly 20% of the window width.
  • The remaining space is occupied by the document-area.
int main(int argc, char **argv)
{
    QApplication a(argc, argv);

    auto createFrame = [](const QString &text, QWidget *parent) {
        QLabel *label = new QLabel(parent);
        label->setFrameStyle(QFrame::Box);
        label->setText(text);
        label->setAlignment(Qt::AlignCenter);
        return label;
    };

    QWidget container;
    QWidget *documentArea = createFrame("document-area", &container);
    QWidget *menuBarArea = createFrame("menu-bar-area", &container);
    QWidget *toolBoxArea = createFrame("tool-box-area", &container);
    QWidget *configBoxArea = createFrame("config-box-area", &container);
    QWidget *statusBarArea = createFrame("status-bar-area", &container);

    AnchorLayout *containerLayout = AnchorLayout::get(&container);

    AnchorLayout *menuBarLayout = AnchorLayout::get(menuBarArea);
    menuBarLayout->left()
                ->anchorTo(containerLayout->left());
    menuBarLayout->right()
                ->anchorTo(containerLayout->right());
    menuBarLayout->top()
                ->anchorTo(containerLayout->top());
    menuBarArea->setFixedHeight(30);

    AnchorLayout *statusBarLayout = AnchorLayout::get(statusBarArea);
    statusBarLayout->left()
                ->anchorTo(containerLayout->left());
    statusBarLayout->right()
                ->anchorTo(containerLayout->right());
    statusBarLayout->bottom()
                ->anchorTo(containerLayout->bottom());
    statusBarArea->setFixedHeight(30);

    AnchorLayout *configBoxLayout = AnchorLayout::get(configBoxArea);
    configBoxLayout->right()
                ->anchorTo(containerLayout->right());
    configBoxLayout->top()
                ->anchorTo(menuBarLayout->bottom())
                ->setMargin(2);
    configBoxLayout->bottom()
                ->anchorTo(statusBarLayout->top())
                ->setMargin(2);
    configBoxLayout->left()
                ->anchorTo(containerLayout->customLine(Qt::Vertical,-0.2));

    AnchorLayout *toolBoxLayout = AnchorLayout::get(toolBoxArea);
    toolBoxLayout->left()
                ->anchorTo(containerLayout->left());
    toolBoxLayout->top()
                ->anchorTo(menuBarLayout->bottom())
                ->setMargin(2);
    toolBoxLayout->bottom()
                ->anchorTo(statusBarLayout->top())
                ->setMargin(2);
    toolBoxLayout->right()
                ->anchorTo(containerLayout->customLine(Qt::Vertical,0.2));

    AnchorLayout *documentAreaLayout = AnchorLayout::get(documentArea);
    documentAreaLayout->left()
                ->anchorTo(toolBoxLayout->right())
                ->setMargin(2);
    documentAreaLayout->top()
                ->anchorTo(toolBoxLayout->top());
    documentAreaLayout->right()
                ->anchorTo(configBoxLayout->left())
                ->setMargin(2);
    documentAreaLayout->bottom()
                ->anchorTo(configBoxLayout->bottom());

    container.resize(600, 400);
    container.show();

    return a.exec();
}

Notice how we are able to easily place areas relative to each other. Notice also how we are able to use setFixedHeight() to specify some hardcoded sizes. Once we have sorted out the placement of areas, we can now go ahead and place widgets within them using traditional QLayouts or using AnchorLayouts.

AnchorLayout does not inherit QLayout

The AnchorLayout class I have implemented does not inherit QLayout. It makes use of event-filters to look up resize events and recalculates placement of anchor-lines. Each anchor-line then cascades its placement to other anchor-lines connected to it. Recursively the entire widget UI is placed and sized. This also means that we can use an AnchorLayout on top of existing layouts. This is especially useful when you want to stack a widget on top of another widget, which may already have a layout, but still want to have control over its placement.

Example: Let’s take Qt’s QMainWindow sample application.

Now, lets say we want to hover a calendar widget on top of the main-window such that it comes exactly above the status-bar area, but horizontally centered. Like this:

Existing main-window layouts do not provide us any facility to accommodate temporary widgets like this. But with AnchorLayout, we can do something like this

MainWindow::MainWindow(const CustomSizeHintMap &customSizeHints,
                       QWidget *parent, Qt::WindowFlags flags)
    : QMainWindow(parent, flags)
{
    // ......

    AnchorLayout *mainWindowLayout = AnchorLayout::get(this);
    AnchorLayout *statusBarLayout = AnchorLayout::get(this->statusBar());

    QCalendarWidget *calendarWidget = new QCalendarWidget(this);
    calendarWidget->setGridVisible(true);

    AnchorLayout *calendarLayout = AnchorLayout::get(calendarWidget);

    calendarLayout->bottom()
            ->anchorTo(statusBarLayout->top())
            ->setMargin(1);
    calendarLayout->horizontalCenter()
            ->anchorTo(mainWindowLayout->horizontalCenter());
    calendarWidget->setFixedSize(350, 200);
}

What if we wanted for the calendar widget to slightly overlap the status bar area, such that the bottom edge of the calendar goes all the way to 50% of the status-bar height?

We just need to make a really small code change.

    calendarLayout->bottom()
            ->anchorTo(statusBarLayout->verticalCenter());

In this example, we are showing a calendar widget. But in a real world application, it is perfectly possible that whenever we select a file to open, we want to show a temporary widget near the status bar like this which shows load-progress. We want for this temporary widget to be visible within the boundary of the main-window; but placed appropriately.

Surely there are plenty of real-world use cases for using an Anchor Layout in Widgets UI. If you want to take the Anchor Layout for a spin, please pull a copy of the sample code from here: https://github.com/pnudupa/anchorlayout.git