PySide-and-QML-Playground: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
m (Another change of quotes to underscores in python)
m (Fix code blocks)
 
(5 intermediate revisions by 4 users not shown)
Line 1: Line 1:




[[Category:LanguageBindings::PySide]]
[[Category:PySide]]




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


<code>
<syntaxhighlight lang="python3">
#!/usr/bin/env python
#!/usr/bin/env python
# -'''- coding: utf-8 -'''-
# -'''- coding: utf-8 -'''-
Line 23: Line 23:
class MainWindow(QDeclarativeView):
class MainWindow(QDeclarativeView):


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


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


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.
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!
So, whatever we declare in '''view.qml''' will appear as the content of our MainWindow, so let's try some things!
Line 49: Line 49:
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:
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:


<code>
<syntaxhighlight lang="qml">
import QtQuick 1.0
import QtQuick 1.0


Line 62: Line 62:
  }
  }
}
}
</code>
</syntaxhighlight>


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.
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.
Line 70: Line 70:
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:
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:


<code>
<syntaxhighlight lang="qml">
import QtQuick 1.0
import QtQuick 1.0


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


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


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


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.
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.
Line 106: Line 106:
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''':
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''':


<code>
<syntaxhighlight lang="qml">
import QtQuick 1.0
import QtQuick 1.0


Line 116: Line 116:
  property alias color: my_text.color
  property alias color: my_text.color


Text {
Text {
id: my_text
  id: my_text
anchors.fill: parent
  anchors.fill: parent
  }
  }
}
}
</code>
</syntaxhighlight>


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.
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'''.
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,
In the next two lines,


<code>
<syntaxhighlight lang="qml">
property alias text: my_text.text
property alias text: my_text.text
property alias color: my_text.color
property alias color: my_text.color
</code>
</syntaxhighlight>


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.
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.
Line 138: Line 138:
Lets change our '''view.qml''' file, which is called by our PySide code to the following:
Lets change our '''view.qml''' file, which is called by our PySide code to the following:


<code>
<syntaxhighlight lang="qml">
import QtQuick 1.0
import QtQuick 1.0


Line 146: Line 146:
  height: 200
  height: 200


Grid {
Grid {
columns: 3
  columns: 3
spacing: 2
  spacing: 2


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

Latest revision as of 13:41, 2 September 2022



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"}
 }
}