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.

  1. // remote.qml
  2. import QtQuick
  3. Rectangle {
  4. width: 320
  5. height: 320
  6. color: '#ff0000'
  7. }

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

  1. cd <PROJECT>
  2. python -m http.server 8080

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

  1. 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:

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

Sweet and simple.

TIP

If the qml program is not in your path, you can find it in the Qt binaries: <qt-install-path>/<qt-version>/<your-os>/bin/qml.

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.

  1. // main.qml
  2. import QtQuick
  3. Loader {
  4. id: root
  5. source: 'http://localhost:8080/Remote.qml'
  6. onLoaded: {
  7. root.width = item.width
  8. root.height = item.height
  9. }
  10. }

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

  1. qml -f main.qml

TIP

If you do not want to run a local server you can also use the gist service from GitHub. The gist is a clipboard like online services like Pastebin and others. It is available under https://gist.github.comServing UI via HTTP - 图1 (opens new window). I created for this example a small gist under the URL https://gist.github.com/jryannel/7983492Serving UI via HTTP - 图2 (opens new window). This will reveal a green rectangle. As the gist URL will provide the website as HTML code we need to attach a /raw to the URL to retrieve the raw file and not the HTML code.

  1. // remote.qml
  2. import QtQuick
  3. Loader {
  4. id: root
  5. source: 'https://gist.github.com/jryannel/7983492/raw'
  6. onLoaded: {
  7. root.width = item.width
  8. root.height = item.height
  9. }
  10. }

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:

  1. ./src/main.qml
  2. ./src/remote/qmldir
  3. ./src/remote/Button.qml
  4. ./src/remote/Remote.qml

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

  1. import QtQuick
  2. Loader {
  3. id: root
  4. anchors.fill: parent
  5. source: 'http://localhost:8080/Remote.qml'
  6. onLoaded: {
  7. root.width = item.width
  8. root.height = item.height
  9. }
  10. }

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:

  1. import QtQuick
  2. Rectangle {
  3. width: 320
  4. height: 320
  5. color: '#ff0000'
  6. Button {
  7. anchors.centerIn: parent
  8. text: 'Click Me'
  9. onClicked: Qt.quit()
  10. }
  11. }

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

  1. Button 1.0 Button.qml

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

  1. import QtQuick.Controls
  2. Button {
  3. }

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

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

And remote QML loader:

  1. 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:

  1. import QtQuick
  2. import "http://localhost:8080" as Remote
  3. Rectangle {
  4. width: 320
  5. height: 320
  6. color: 'blue'
  7. Remote.Button {
  8. anchors.centerIn: parent
  9. text: 'Quit'
  10. onClicked: Qt.quit()
  11. }
  12. }

TIP

When using components from a local file system, they are created immediately without a latency. When components are loaded via the network they are created asynchronously. This has the effect that the time of creation is unknown and an element may not yet be fully loaded when others are already completed. Take this into account when working with components loaded over the network.