QML and Qt for Python interaction

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.


Blog Topics:

Comments