Serving UI via HTTP

To load a simple user interface via HTTP we need to have a web-server, which serves the UI documents. We start off with our own simple web-server using a python one-liner. But first, we need to have our demo user interface. For this, we create a small Remote.qml file in our project folder and create a red rectangle inside.

// remote.qml
import QtQuick

Rectangle {
    width: 320
    height: 320
    color: '#ff0000'
}

To serve this file we can start a small python script:

cd <PROJECT>
python -m http.server 8080

Now our file should be reachable via http://localhost:8080/Remote.qml. You can test it with:

curl http://localhost:8080/Remote.qml

Or just point your browser to the location. Your browser does not understand QML and will not be able to render the document through.

Hopefully, Qt 6 provides such a browser in the form of the qml binary. You can directly load a remote QML document by using the following command:

qml -f http://localhost:8080/Remote.qml

Sweet and simple.

Another way of importing a remote QML document is to dynamically load it using QML ! For this, we use a Loader element to retrieve for us the remote document.

// main.qml
import QtQuick

Loader {
    id: root
    source: 'http://localhost:8080/Remote.qml'
    onLoaded: {
        root.width = item.width
        root.height = item.height
    }
}

Now we can ask the qml executable to load the local main.qml loader document.

qml -f main.qml
// remote.qml
import QtQuick

Loader {
    id: root
    source: 'https://gist.github.com/jryannel/7983492/raw'
    onLoaded: {
        root.width = item.width
        root.height = item.height
    }
}

To load another file over the network from Remote.qml, you will need to create a dedicated qmldir file in the same directory on the server. Once done, you will be able to reference the component by its name.

Networked Components

Let us create a small experiment. We add to our remote side a small button as a reusable component.

Here's the directory structure that we will use:

./src/main.qml
./src/remote/qmldir
./src/remote/Button.qml
./src/remote/Remote.qml

Our main.qml is the same as in our previous example:

import QtQuick

Loader {
    id: root
    anchors.fill: parent
    source: 'http://localhost:8080/Remote.qml'
    onLoaded: {
        root.width = item.width
        root.height = item.height
    }
}

In the remote directory, we will update the Remote.qml file so that it uses a custom Button component coming from our own remote Button.qml file:

import QtQuick

Rectangle {
    width: 320
    height: 320
    color: '#ff0000'

    Button {
        anchors.centerIn: parent
        text: 'Click Me'
        onClicked: Qt.quit()
    }
}

Using a qmldir, we will define the content of our (remote) QML directory:

Button 1.0 Button.qml

And finally we will create our dummy Button.qml file:

import QtQuick.Controls

Button {
    
}

We can now launch our web-server (keep in mind that we now have a remote subdirectory):

cd src
python -m http.server --directory ./remote 8080

And remote QML loader:

qml -f main.qml

Importing a QML components directory

By defining a qmldir file, it's also possible to directly import a library of components from a remote repository. To do so, a classical import works:

import QtQuick
import "http://localhost:8080" as Remote

Rectangle {
    width: 320
    height: 320
    color: 'blue'

    Remote.Button {
        anchors.centerIn: parent
        text: 'Quit'
        onClicked: Qt.quit()
    }
}

Last updated