Creating a Mobile Application
This tutorial describes developing Qt Quick applications for Android and iOS devices using Qt Quick Controls. We use Qt Creator to implement a Qt Quick application that accelerates an SVG (Scalable Vector Graphics) image based on the changing accelerometer values.
Setting up the Development Environment
To be able to build and run the application on a mobile device, you must set up the development environment for the device platform and configure a connection between Qt Creator and the mobile device.
To develop for Android devices, you must download and install the latest Android NDK and SDK, and update the SDK to get the API and tools needed for development. In addition, you must install the Java SE Development Kit (JDK) and Apache Ant. After you have installed all these tools, you must specify the paths to them in Qt Creator. For detailed instructions, see Qt for Android and Connecting Android Devices.
To develop for iOS devices, you must install Xcode and use it to configure a device. For this, you need an Apple developer account and iOS Developer Program certificate that you receive from Apple. For more information, see Connecting iOS Devices.
Creating the Project
- Select File > New File or Project > Application > Qt Quick Application > Choose.
- In the Name field, type accelbubble.
- In the Create in field, enter the path for the project files. For example,
C:\Qt\examples
, and then click Next (or Continue on OS X). - In the Qt Quick component set field, select Qt Quick Controls 1.1.
- Select kits for Android ARM and iPhone OS, and click Next.
Note: Kits are listed if they have been specified in Tools > Options > Build & Run > Kits (on Windows and Linux) or in Qt Creator > Preferences Build & Run > Kits (on OS X).
- Select Next in the following dialogs to use the default settings.
- Review the project settings, and click Finish (or Done on OS X).
Qt Creator generates a default QML file that you can modify to create the main view of the application.
Creating the Main View
The main view of the application displays an SVG bubble image at the center of the main window.
To use the Bluebubble.svg used by the Qt Sensors example, Accel Bubble, in your project, you must copy it to the project directory (same subdirectory as the QML file) from the examples directory in the Qt installation directory. For example: C:\Qt\Qt5.2.0\5.2.0\msvc2010\examples\sensors\accelbubble\content
. The image appears in Resources. You can also use any other image or a QML type, instead.
- In the Projects view, double-click the main.qml file to open it in the code editor.
- Modify the properties of the ApplicationWindow type to specify the application name, give the ApplicationWindow an id, and to set it visible, as illustrated by the following code snippet:
ApplicationWindow { title: qsTr("Accelerate Bubble") id: mainWindow width: 640 height: 480 visible: true }
- Click Design to open the file in Qt Quick Designer.
- In the Navigator, select Label and press Delete to delete it.
- In Library > Resources, select Bluebubble.svg and drag and drop it to the canvas.
- In the Properties pane, Id field, enter bubble to be able to reference the image from other places.
- In the code editor, add the following new properties to the image to position the image at the center of ApplicationWindow when the application starts:
Image { id: bubble source: "Bluebubble.svg" smooth: true property real centerX: mainWindow.width / 2 property real centerY: mainWindow.height / 2 property real bubbleCenter: bubble.width / 2
- Set the x and y position of the image based on the new properties:
... x: centerX - bubbleCenter y: centerY - bubbleCenter }
Here is how the accelbubble.qml file looks after you made the changes:
import QtQuick 2.2 import QtQuick.Controls 1.1 ApplicationWindow { title: qsTr("Accelerate Bubble") id: mainWindow width: 640 height: 480 visible: true Image { id: bubble source: "Bluebubble.svg" smooth: true property real centerX: mainWindow.width / 2 property real centerY: mainWindow.height / 2 property real bubbleCenter: bubble.width / 2 x: centerX - bubbleCenter y: centerY - bubbleCenter }
Moving the Bubble
Now that the visual elements are in place, let us move the bubble based on Accelerometer sensor values.
- Add the following import statement to main.qml:
import QtSensors 5.0
- Add the Accelerometer type with the necessary properties:
Accelerometer { id: accel dataRate: 100 active:true }
- Add the following JavaScript functions that calculate the x and y position of the bubble based on the current Accelerometer values:
function calcPitch(x, y, z) { return -(Math.atan(y / Math.sqrt(x * x + z * z)) * 57.2957795); } function calcRoll(x, y, z) { return -(Math.atan(x / Math.sqrt(y * y + z * z)) * 57.2957795); }
- Add the following JavaScript code for onReadingChanged signal of Accelerometer type to make the bubble move when the Accelerometer values change:
onReadingChanged: { var newX = (bubble.x + calcRoll(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1) var newY = (bubble.y - calcPitch(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1) if (isNaN(newX) || isNaN(newY)) return; if (newX < 0) newX = 0 if (newX > mainWindow.width - bubble.width) newX = mainWindow.width - bubble.width if (newY < 18) newY = 18 if (newY > mainWindow.height - bubble.height) newY = mainWindow.height - bubble.height bubble.x = newX bubble.y = newY }
We want to ensure that the position of the bubble is always within the bounds of the screen. If the Accelerometer returns not a number (NaN), the value is ignored and the bubble position is not updated.
- Add SmoothedAnimation behavior on the x and y properties of the bubble to make its movement look smoother.
Behavior on y { SmoothedAnimation { easing.type: Easing.Linear duration: 100 } } Behavior on x { SmoothedAnimation { easing.type: Easing.Linear duration: 100 } }
Locking Device Orientation
The device display is rotated by default when the device orientation changes between portrait and landscape. For this example, it would be better for the screen orientation to be fixed.
To lock the orientation to portrait or landscape on Android, specify it in an AndroidManifest.xml that you can generate in Qt Creator. For more information, see Editing Manifest Files.
On iOS, you can lock the device orientation in a Info.plist file that you specify in the .pro file as the value of the QMAKE_INFO_PLIST variable.
Adding Dependencies
Update the accelbubble.pro file with the following library dependency information:
QT += quick sensors svg xml
On iOS, you must link to the above libraries statically, by adding the plugin names explicitly as values of the QTPLUGIN variable. Specify a qmake scope for iOS builds (which can also contain the QMAKE_INFO_PLIST variable):
ios { QTPLUGIN += qsvg qsvgicon qtsensors_ios QMAKE_INFO_PLIST = Info.plist }
After adding the dependencies, select Build > Run qmake to apply the changes to the Makefile of the project.
Adding Resources
You need to add the Bluebubble.svg image file to the application resources for deployment to mobile devices:
- In the Projects view, double-click the qml.qrc file to open it in the resource editor.
- Select Add to add Bluebubble.svg.
Running the Application
The application is complete and ready to be deployed to a device:
- Enable USB Debugging on the Android device or developer mode on the iOS device.
- Connect the device to the development PC.
If you are using a device running Android v4.2.2, it should prompt you to verify the connection to allow USB debugging from the PC it is connected to. To avoid such prompts every time you connect the device, check "Always allow from the computer" and select OK.
- To run the application on the device, press Ctrl+R.
Example Code
When you have completed the steps, the main.qml file should look as follows:
import QtQuick 2.2 import QtQuick.Controls 1.1 import QtSensors 5.0 ApplicationWindow { title: qsTr("Accelerate Bubble") id: mainWindow width: 640 height: 480 visible: true Image { id: bubble source: "Bluebubble.svg" smooth: true property real centerX: mainWindow.width / 2 property real centerY: mainWindow.height / 2 property real bubbleCenter: bubble.width / 2 x: centerX - bubbleCenter y: centerY - bubbleCenter Behavior on y { SmoothedAnimation { easing.type: Easing.Linear duration: 100 } } Behavior on x { SmoothedAnimation { easing.type: Easing.Linear duration: 100 } } } Accelerometer { id: accel dataRate: 100 active:true onReadingChanged: { var newX = (bubble.x + calcRoll(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1) var newY = (bubble.y - calcPitch(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1) if (isNaN(newX) || isNaN(newY)) return; if (newX < 0) newX = 0 if (newX > mainWindow.width - bubble.width) newX = mainWindow.width - bubble.width if (newY < 18) newY = 18 if (newY > mainWindow.height - bubble.height) newY = mainWindow.height - bubble.height bubble.x = newX bubble.y = newY } } function calcPitch(x, y, z) { return -(Math.atan(y / Math.sqrt(x * x + z * z)) * 57.2957795); } function calcRoll(x, y, z) { return -(Math.atan(x / Math.sqrt(y * y + z * z)) * 57.2957795); } menuBar: MenuBar { Menu { title: qsTr("File") MenuItem { text: qsTr("&Open") onTriggered: console.log("Open action triggered"); } MenuItem { text: qsTr("Exit") onTriggered: Qt.quit(); } } } }
© 2015 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.