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:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3.  
  4. import sys
  5. from PySide.QtCore import *
  6. from PySide.QtGui import *
  7. from PySide.QtDeclarative import *
  8.  
  9. # Our main window
  10. class MainWindow(QDeclarativeView):
  11.    
  12.     def __init__(self, parent=None):
  13.         super(MainWindow, self).__init__(parent)
  14.         self.setWindowTitle("Main Window")
  15.         # Renders 'view.qml'
  16.         self.setSource(QUrl.fromLocalFile('view.qml'))
  17.         # QML resizes to main window
  18.         self.setResizeMode(QDeclarativeView.SizeRootObjectToView)
  19.  
  20.  
  21. if __name__ == '__main__':
  22.     # Create the Qt Application
  23.     app = QApplication(sys.argv)
  24.     # Create and show the main window
  25.     window = MainWindow()
  26.     window.show()
  27.     # Run the main Qt loop
  28.     sys.exit(app.exec_())

If you know already 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:

  1. import QtQuick 1.0
  2.  
  3. Rectangle {
  4.     width: 200
  5.     height: 200
  6.     color: "red"    
  7.  
  8.     Text {
  9.         text: "Hello World"
  10.         anchors.centerIn: parent
  11.     }
  12. }

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:

  1. import QtQuick 1.0
  2.  
  3. Rectangle {
  4.     width: 200
  5.     height: 200
  6.     color: "white"
  7.  
  8.     Text {
  9.         text: "Hello World"
  10.         anchors.centerIn: parent
  11.         font.pixelSize: 24
  12.         color: 'black'
  13.        
  14.         MouseArea {
  15.             anchors.fill: parent
  16.             onClicked: {
  17.                 console.log("Mouse clicked!", parent.color)
  18.                 if (parent.color == "#000000")
  19.                     parent.color = 'blue';
  20.                 else
  21.                     parent.color = 'black';                
  22.             }
  23.         }
  24.     }
  25. }

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

  1. if (parent.color == "#000000")
because if we used
  1. 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:

  1. import QtQuick 1.0
  2.  
  3. Item {
  4.     id: my_container
  5.     width: 30
  6.     height: 10
  7.     property alias text: my_text.text
  8.     property alias color: my_text.color        
  9.    
  10.     Text {
  11.         id: my_text
  12.         anchors.fill: parent
  13.     }    
  14. }

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.

Out 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,

  1. property alias text: my_text.text
  2. 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:

  1. import QtQuick 1.0
  2.  
  3. Rectangle {
  4.     id: main_window
  5.     width: 200
  6.     height: 200
  7.  
  8.     Grid {
  9.         columns: 3
  10.         spacing: 2        
  11.        
  12.         String {text: "One"; color: "red"}
  13.         String {text: "Two"; color: "green"}
  14.         String {text: "Three"; color: "blue"}
  15.         String {text: "Four"; color: "black"}
  16.         String {text: "Five"; color: "yellow"}
  17.         String {text: "Six"; color: "pink"}        
  18.      }
  19. }

So, we have a Rectangle in the main window and a Grid element with 3 columns spaced by 2 (pixels). The only novelty here is that we are using String {text: “xxx”; color: “xxx”} to call our String.qml element with the exact properties we want. Using this instead of 6 calls to a Text element saves many code. But this is a simple example, and your String element could be more complex, so, in this way you can make your code more campact and simpler.

Categories: