QML and Qt for Python interaction

Published Monday May 14th, 2018
7 Comments on QML and Qt for Python interaction
Posted in Qt for Python

Besides QtWidgets for desktop applications, Qt has another UI technology, QML.
Today, I would like to show how QML interacts with Qt for Python, roughly based on the tutorial example declarative/extending/chapter3-bindings.

First, let’s have a look at the typical boiler plate code for loading a .qml file. We instantiate a QGuiApplication and a QQuickView.
We set its resize mode property to SizeRootObjectToView so that the QML element is expanded to the view size.

app = QGuiApplication(sys.argv)
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView)

We then instruct the view to load the QML file, using the method setSource.
Since a QML file typically is to be found next to the Python script, we construct a complete path using functions of the os module:

current_path = os.path.abspath(os.path.dirname(__file__))
qml_file = os.path.join(current_path, 'app.qml')
view.setSource(QUrl.fromLocalFile(qmlFile))
if view.status() == QQuickView.Error:
    sys.exit(-1)

Now, the view can be shown and the application run. To ensure the correct destruction order, del must be invoked on the view object before quitting the application

view.show()
res = app.exec_()
del view
sys.exit(res)

With this code, we can display QML files. For example, a minimal hello world is shown when creating app.qml as follows:

import QtQuick 2.0

Text {
    text : 'Hello, world!'
}

Extending QML by using classes written in Python

Let’s implement something on top of QQuickPaintedItem:

class PieChart (QQuickPaintedItem):
    def __init__(self, parent = None):
        QQuickPaintedItem.__init__(self, parent)
        self.color = QColor()

    def paint(self, painter):
        pen = QPen(self.color, 2)
        painter.setPen(pen);
        painter.setRenderHints(QPainter.Antialiasing, True);
        # From drawPie(const QRect &rect, int startAngle, int spanAngle)
        painter.drawPie(self.boundingRect().adjusted(1,1,-1,-1),
            90 * 16, 290 * 16);

    def getColor(self):
        return self.color

    def setColor(self, value):
        if value != self.color:
            self.color = value
            self.update()
            self.colorChanged.emit()

    colorChanged = Signal()
    color = Property(QColor, getColor, setColor, notify=colorChanged)

This overrides the QQuickPaintedItem.paint() method to draw simple pie chart. The color is defined as property so that it is exposed to Qt. To make the type known to QML, we insert:

qmlRegisterType(PieChart, 'Charts', 1, 0, 'PieChart');

right after creating the QGuiApplication.

app.qml can then be changed to:

import Charts 1.0
import QtQuick 2.0

Item {
    width: 300; height: 200

    PieChart {
        id: chartA
        width: 100; height: 100
        color: "red"
        anchors.centerIn:parent
    }

    MouseArea {
        anchors.fill: parent
        onClicked: { chartA.color = "blue" }
    }

    Text {
        anchors {
            bottom: parent.bottom;
            horizontalCenter: parent.horizontalCenter;
            bottomMargin: 20
        }
        text: "Click anywhere to change the chart color"
    }
}

for our custom type to appear.
Additionally, clicking with the mouse will change the color property.

Do you like this? Share it
Share on LinkedInGoogle+Share on FacebookTweet about this on Twitter

Posted in Qt for Python

7 comments

jason says:

I don’t understand why anyone would want to add yet another language to their tech proficiency stack. The renewed interest in Python is misguided (It’s AI driving the rise in popularity, not apps). If you want Qt+Python, then you should be able to remove V4 and add Python as the QML scripting language. However, after many years of QMLing, I think JS is the right choice.

The above code example adds nothing of value to QML, or Qt.

What you should be focusing on is a proper web runtime so that Web Developers can use QML instead of Electron, ReactNative, etc.

I’d like to know where it is documented that the rise in popularity for python, as noted on this blog, is associated with application development?

Will says:

> It’s AI driving the rise in popularity, not apps

You may be experiencing some selection bias when trying to judge a range of industries. I have worked actively in Python in all of my jobs in recent years including in the financial industry, VFX, Internet infrastructure, and I have nothing to do with AI or machine learning. It’s an extremely common and useful language for a range of applications.

Personally, I find hacking PyQt on the Python REPL to be infinitely more fun and efficient than dealing with any JS web runtime stuff, and I have embedded the Python runtime into my C++ apps. There’s already like 7 areas on the forum that are named after some variation of “QtWebFoo,” “WebFoo for Qt,” etc. I dunno that more focus on web developers is the biggest hole in what Qt offers right now.

Alexander says:

I strongly disagree. I have used Qt/C++ for many years now. C++ is a great language and a requirement for very conservative industries such as automotive for example. However, one of my customers uses Python for most of their work, so I started to use PyQt. I instantly fell in love with how easy it is to work with Python and Qt compared to C++ and Qt. Most of the boilerplate code is not necessary when working Python and the biggest plus for me is good support for testing compared to C++. Of course one can test C++ applications, however, writing the tests is much more painful due to the compiled and static nature of the language.

Regarding web: I learned Angular some time ago to compare it with Qt. I have to say it’s nice if you are web developer, however, for the desktop and industrial HMIs (where I use Qt) it’s completely worthless. Web applications are designed for massive parallel use and therefore require a much more complex back-end to front-end logic than normal QT desktop application. Exposing models to QML just feels natural, writing a REST or WebSocket API just to show some data is not, in my opinion.

pat moran says:

Fantastic! I would like to see some screenshots of the actual results.

Yes I use Python – The repl is invaluable for learning the library especially when coupled with a good IDE like PyCharm.

Thanks!

zahraee says:

I totally agree with @jason , Focusing on enabling web technologies in QML is better than support adding a language to your portfolio,

Lukas Hetzenecker says:

I stongly disagree with the above comments.

Designing user interfaces using QML is a joy – but I always had to write the backend in C++, which – honestly – was a pain in the ass. Python is great for building prototypes. Python offers so many features out of the box in a simple, intuitive way.

I built a smart mirror, with the whole user interface in QML. Therefore the UI is easily customizable, layout and such can be adjusted in a single line of code even by non-programmers.

But for the whole data providers I used Python (with the PyQt bindings, because Qt for Python isn’t ready yet). Fetching public transportation data end emitting those to QML was possible in less than 30 lines of code. Getting that didn’t even take me half an hour. The code looks so intuitive – i could just the python features like asynchronous I/O with coroutines.

Connecting to a smart home system via a websocket connection was another module, again with the bare minimum of time and lines of code required. Python offers a module for Google Assistant, which was also easily integrated. Face recognition? Python has a great module for that!

I think enriching the Qt ecosystem with Python is the best thing that could have happened to Qt! A hunge thank you from my side for taking that step!

Lukas Hetzenecker says:

I can understand the critisism that the mentioned example does not highlight the necessity for adding Python support.
After all, the same code can be translated to C++ line-by-line.

If you want to see where Python really shines, please have a look at that code:
https://gist.github.com/lukas-hetzenecker/e8f8479275fb8df0ed24ab993bb02532

This shows two QML modules in Python, a google assistant integration for QML, and a Home-Assistant integration.

The services can then be used like:

“`
AssistantService {
id: assistantService
credentials: “config/credentials.json”
Component.onCompleted: {
this.start()
}
“`

Leave a Reply

Your email address will not be published.

Get started today with Qt Download now