How to do it…

Let's get started by following this step-by-step guide:

  1.  Create a new Qt Quick application – Empty project.
  2. In Qt Creator, right-click on qml.qrc and select Open in Editor. Then, click Add | Add Files and add tux.png to the project as follows:

  1. Next, open up MainForm.ui.qml. Drag an image widget from the Library window to the canvas. Then, set the source of the image to tux.png and set its fillMode to PreserveAspectFit. After that, set its width to 200 and its height to 220.
  2. Make sure that both the mouse area widget and the image widget are exported as alias properties of the root item by clicking on the small icon besides their respective widget name.
  3. After that, switch over to the script editor by clicking on the Edit button on the side bar located at the left side of the editor. We need to change the mouse area widget to a multi-point touch area widget, as in the following code:
MultiPointTouchArea {
id: touchArea
anchors.fill: parent
touchPoints: [
TouchPoint { id: point1 },
TouchPoint { id: point2 }
]
}
  1. We also set the Image widget to be automatically placed at the center of the window by default as follows:
Image {
id: tux
x: (window.width / 2) - (tux.width / 2)
y: (window.height / 2) - (tux.height / 2)
width: 200
height: 220
fillMode: Image.PreserveAspectFit
source: "tux.png"
}
  1. The final user interface should look something like this:

  1. Once you're done with that, let's open up main.qml. First, clear everything within the MainForm object except anchors.fill: parent, as shown in the following code:
import QtQuick 2.9
import QtQuick.Window 2.3
Window {
visible: true
MainForm {
anchors.fill: parent
}
}
  1. After that, declare several variables within the MainForm object that will be used to rescale the image widget. If you want to know more about the property keyword used in the following code, check out the There's more… section at the end of this example:
property int prevPointX: 0
property int prevPointY: 0
property int curPointX: 0
property int curPointY: 0
property int prevDistX: 0
property int prevDistY: 0
property int curDistX: 0
property int curDistY: 0
property int tuxWidth: tux.width
property int tuxHeight: tux.height
  1. Using the following code, we will define what will happen when our finger touches the multi-point area widget. In this case, we will save the positions of the first and second touch points if more than one finger touches the multi-point touch area. We also save the width and height of the image widget so that, later on, we can use these variables to calculate the scale of the image when the fingers start to move:
touchArea.onPressed: {
if (touchArea.touchPoints[1].pressed) {
if (touchArea.touchPoints[1].x < touchArea.touchPoints[0].x)
prevDistX = touchArea.touchPoints[1].x - touchArea.touchPoints[0].x
else
prevDistX = touchArea.touchPoints[0].x - touchArea.touchPoints[1].x
if (touchArea.touchPoints[1].y < touchArea.touchPoints[0].y)
prevDistY = touchArea.touchPoints[1].y - touchArea.touchPoints[0].y
else
prevDistY = touchArea.touchPoints[0].y - touchArea.touchPoints[1].y
tuxWidth = tux.width
tuxHeight = tux.height
}
}
  1. The following diagram shows the example of touch points being registered when two fingers are touching the screen within the touchArea boundary. The touchArea.touchPoints[0] is the first registered touch point and touchArea.touchPoints[1] is the second. We then calculate the X and Y distance between the two touch points and save them as prevDistX and prevDistY as follows:

  1. After that, we will define what will happen when our fingers move while remaining in contact with the screen and still within the boundary of the touch area using the following code. At this point, we will calculate the scale of the image by using the variables we saved in the previous step. At the same time, if we detect that only a single touch is found, then we will move the image instead of altering its scale:
touchArea.onUpdated: {
if (!touchArea.touchPoints[1].pressed) {
tux.x += touchArea.touchPoints[0].x - touchArea.touchPoints[0].previousX
tux.y += touchArea.touchPoints[0].y - touchArea.touchPoints[0].previousY
}
else {
if (touchArea.touchPoints[1].x < touchArea.touchPoints[0].x)
curDistX = touchArea.touchPoints[1].x - touchArea.touchPoints[0].x
else
curDistX = touchArea.touchPoints[0].x - touchArea.touchPoints[1].x
if (touchArea.touchPoints[1].y < touchArea.touchPoints[0].y)
curDistY = touchArea.touchPoints[1].y - touchArea.touchPoints[0].y
else
curDistY = touchArea.touchPoints[0].y - touchArea.touchPoints[1].y
tux.width = tuxWidth + prevDistX - curDistX
tux.height = tuxHeight + prevDistY - curDistY
}
}
  1. The following diagram shows the example of moving touch points – touchArea.touchPoints[0] moved from point A to point B while touchArea.touchPoints[1] moved from point C to point D. We can then determine how many units have the touch points moved by looking at the differences between the previous X, Y variables with the current ones:

  1. You can now build and export the program to your mobile device. You will not be able to test this program on a platform that does not support multi-touch. Once the program is running on the mobile device (or a desktop/laptop that supports multi-touch), try two things—put only one finger on the screen and move it around, and put two fingers on the screen and move them in opposite directions. What you should see is that the penguin will be moved to another place if you use only one finger, and it will be scaled up or down if you use two fingers, as shown in the following screenshot: