PySide-and-QML-Playground

From Qt Wiki
Jump to navigation Jump to search



PySide and Qt Quick/QML Playground

If you have followed Hello World in PySide and QtQuick, you should now know how to create a PySide application which opens and renders a QML file. In this tutorial we will show you some simple examples just to get you more acquainted with this new technology.

First, we will start with a basic PySide stub file which will be updated as needed. Let's name it main.py:

#!/usr/bin/env python
# -'''- coding: utf-8 -'''-

import sys
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtDeclarative import *

# Our main window
class MainWindow(QDeclarativeView):

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setWindowTitle("Main Window")
        # Renders 'view.qml'
        self.setSource(QUrl.fromLocalFile('view.qml'))
        # QML resizes to main window
        self.setResizeMode(QDeclarativeView.SizeRootObjectToView)

if __name__ == '__main__':
    # Create the Qt Application
    app = QApplication(sys.argv)
    # Create and show the main window
    window = MainWindow()
    window.show()
    # Run the main Qt loop
    sys.exit(app.exec_())

If you already know PySide, we are just subclassing QDeclarativeView (which handles QML files), and setting the source to a file called view.qml which is in the same folder as our main.py file. Also, the QML root element of our view.qml will resize to the size of the outer window because we are using self.setResizeMode(QDeclarativeView.SizeRootObjectToView). In the main function, we are just creating a Qt Application, and creating/showing our main window.

So, whatever we declare in view.qml will appear as the content of our MainWindow, so let's try some things!

Hello World

Let's start with a simple example, like the one we gave on Hello World in PySide and QtQuick. So set your view.qml like the following:

import QtQuick 1.0

Rectangle {
 width: 200
 height: 200
 color: "red"

Text {
 text: "Hello World"
 anchors.centerIn: parent
 }
}

Simple example, which shows a red rectangle with "Hello World" in the center. If you try to resize the main window, you can see that the rectangle also resizes and that the text keeps centered.

Catch Mouse clicks and change colors

In this next example, we are changing the previous one in order to listen to mouse clicks over the Hello World text, and toggle the color from black to blue and vice-versa. Here is the code, just name it the same view.qml and try it with the same PySide code:

import QtQuick 1.0

Rectangle {
    width: 200
    height: 200
    color: "white"

    Text {
        text: "Hello World"
        anchors.centerIn: parent
        font.pixelSize: 24
        color: 'black'

        MouseArea {
            anchors.fill: parent
            onClicked: {
                console.log("Mouse clicked!", parent.color)
                if (parent.color == "#000000")
                    parent.color = 'blue';
                else
                    parent.color = 'black';
            }
        }
    }
}

The main differences from the Hello World example are in lines 11 to 23. Considering the Text element, we are justing setting a black color to it and changing the size of the text to 24 pixels (lines 11 and 12). The other difference is the new element MouseArea. Basically, a MouseArea is an element which responds to mouse interactions. So, in line 15, with anchors.fill: parent we are just saying that the area for the mouse has the same size as its parent, the Text. So, the bigger the Text, the bigger the mouse area. You can think of a MouseArea like a transparent area on front of the Text.

Finally, the toggle is implemented in the onClicked signal handling. In this function we just ouput something to the console and test if the parent color is black. If so, we change it to blue, else, we change it to black. We have to use

if (parent.color  "#000000")

because if we used

if (parent.color  'black')

as it would be intuitive, we would be comparing a color to a regular string, which does not work.

Custom components

In Qt Quick it is possible to reuse standard components to create custom and more complex components. In this section we are going to create a custom component which we will call String and we will use it to draw a line of text of a certain color. The next piece of code, represents our custom element, call it String.qml:

import QtQuick 1.0

Item {
 id: my_container
 width: 30
 height: 10
 property alias text: my_text.text
 property alias color: my_text.color

 Text {
  id: my_text
  anchors.fill: parent
 }
}

Make sure you use the name String.qml for the file, because if we want to use this element in other QML files, we must call it by the filename. Also, you are advised to respect the uppercase in the first letter, to distinguish standard python modules or other files from QML Elements.

Our String.qml starts with an element Item, which is the most basic UI element of QML. We name it my_container by using the id property. We also set some values for the size. If you have followed the previous QML examples, you will also recognize the Text element, which we have added the id my_text.

In the next two lines,

property alias text: my_text.text
property alias color: my_text.color

we are declaring two new properties called "text" and "color". Both properties are just alias to access the respective properties in the Text element. So when we are changing the String element color, we are in fact changing the color of the Text element.

Lets change our view.qml file, which is called by our PySide code to the following:

import QtQuick 1.0

Rectangle {
 id: main_window
 width: 200
 height: 200

 Grid {
  columns: 3
  spacing: 2

  String {text: "One"; color: "red"}
  String {text: "Two"; color: "green"}
  String {text: "Three"; color: "blue"}
  String {text: "Four"; color: "black"}
  String {text: "Five"; color: "yellow"}
  String {text: "Six"; color: "pink"}
 }
}