Positioning Elements

There are a number of QML elements used to position items. These are called positioners, of which the Qt Quick module provides the following: Row, Column, Grid and Flow. They can be seen showing the same contents in the illustration below.

TIP

Before we go into details, let me introduce some helper elements: the red, blue, green, lighter and darker squares. Each of these components contains a 48x48 pixel colorized rectangle. As a reference, here is the source code for the RedSquare:

  1. // RedSquare.qml
  2. import QtQuick
  3. Rectangle {
  4. width: 48
  5. height: 48
  6. color: "#ea7025"
  7. border.color: Qt.lighter(color)
  8. }

Please note the use of Qt.lighter(color) to produce a lighter border color based on the fill color. We will use these helpers in the next examples to make the source code more compact and readable. Please remember, each rectangle is initially 48x48 pixels.

The Column element arranges child items into a column by stacking them on top of each other. The spacing property can be used to distance each of the child elements from each other.

Positioning Elements - 图1

  1. // column.qml
  2. import QtQuick
  3. DarkSquare {
  4. id: root
  5. width: 120
  6. height: 240
  7. Column {
  8. id: row
  9. anchors.centerIn: parent
  10. spacing: 8
  11. RedSquare { }
  12. GreenSquare { width: 96 }
  13. BlueSquare { }
  14. }
  15. }

The Row element places its child items next to each other, either from the left to the right, or from the right to the left, depending on the layoutDirection property. Again, spacing is used to separate child items.

Positioning Elements - 图2

  1. // row.qml
  2. import QtQuick
  3. BrightSquare {
  4. id: root
  5. width: 400; height: 120
  6. Row {
  7. id: row
  8. anchors.centerIn: parent
  9. spacing: 20
  10. BlueSquare { }
  11. GreenSquare { }
  12. RedSquare { }
  13. }
  14. }

The Grid element arranges its children in a grid. By setting the rows and columns properties, the number of rows or columns can be constrained. By not setting either of them, the other is calculated from the number of child items. For instance, setting rows to 3 and adding 6 child items will result in 2 columns. The properties flow and layoutDirection are used to control the order in which the items are added to the grid, while spacing controls the amount of space separating the child items.

Positioning Elements - 图3

  1. // grid.qml
  2. import QtQuick
  3. BrightSquare {
  4. id: root
  5. width: 160
  6. height: 160
  7. Grid {
  8. id: grid
  9. rows: 2
  10. columns: 2
  11. anchors.centerIn: parent
  12. spacing: 8
  13. RedSquare { }
  14. RedSquare { }
  15. RedSquare { }
  16. RedSquare { }
  17. }
  18. }

The final positioner is Flow. It adds its child items in a flow. The direction of the flow is controlled using flow and layoutDirection. It can run sideways or from the top to the bottom. It can also run from left to right or in the opposite direction. As the items are added in the flow, they are wrapped to form new rows or columns as needed. In order for a flow to work, it must have a width or a height. This can be set either directly, or though anchor layouts.

Positioning Elements - 图4

  1. // flow.qml
  2. import QtQuick
  3. BrightSquare {
  4. id: root
  5. width: 160
  6. height: 160
  7. Flow {
  8. anchors.fill: parent
  9. anchors.margins: 20
  10. spacing: 20
  11. RedSquare { }
  12. BlueSquare { }
  13. GreenSquare { }
  14. }
  15. }

An element often used with positioners is the Repeater. It works like a for-loop and iterates over a model. In the simplest case a model is just a value providing the number of loops.

Positioning Elements - 图5

  1. // repeater.qml
  2. import QtQuick
  3. DarkSquare {
  4. id: root
  5. width: 252
  6. height: 252
  7. property variant colorArray: ["#00bde3", "#67c111", "#ea7025"]
  8. Grid{
  9. anchors.fill: parent
  10. anchors.margins: 8
  11. spacing: 4
  12. Repeater {
  13. model: 16
  14. Rectangle {
  15. width: 56; height: 56
  16. property int colorIndex: Math.floor(Math.random()*3)
  17. color: root.colorArray[colorIndex]
  18. border.color: Qt.lighter(color)
  19. Text {
  20. anchors.centerIn: parent
  21. color: "#f0f0f0"
  22. text: "Cell " + index
  23. }
  24. }
  25. }
  26. }
  27. }

In this repeater example, we use some new magic. We define our own colorArray property, which is an array of colors. The repeater creates a series of rectangles (16, as defined by the model). For each loop, it creates the rectangle as defined by the child of the repeater. In the rectangle we chose the color by using JS math functions: Math.floor(Math.random()\*3). This gives us a random number in the range from 0..2, which we use to select the color from our color array. As noted earlier, JavaScript is a core part of Qt Quick, and as such, the standard libraries are available to us.

A repeater injects the index property into the repeater. It contains the current loop-index. (0,1,..15). We can use this to make our own decisions based on the index, or in our case to visualize the current index with the Text element.

TIP

More advanced handling of larger models and kinetic views with dynamic delegates is covered in its own model-view chapter. Repeaters are best used when having a small amount of static data to be presented.