Doc: Update the Qt Quick Mobile application tutorial

Remove references to using visual editors and use the example code
from Qt Sensors module.

Add instructions for using CMake.

Add CMakeLists.txt, AndroidManifest.xml, and Info.plist files.

Change-Id: I956379fdf7d39161f571893d56250ec2dd2f5ddd
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
Leena Miettinen
2021-10-07 16:56:11 +02:00
parent d68bb4687c
commit b67482480e
10 changed files with 283 additions and 290 deletions

View File

@@ -0,0 +1,44 @@
<?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.qtproject.example"
android:installLocation="auto"
android:versionCode="-- %%INSERT_VERSION_CODE%% --"
android:versionName="-- %%INSERT_VERSION_NAME%% --">
<!-- %%INSERT_PERMISSIONS -->
<!-- %%INSERT_FEATURES -->
<supports-screens
android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true" />
<application
android:name="org.qtproject.qt.android.bindings.QtApplication"
android:extractNativeLibs="true"
android:hardwareAccelerated="true"
android:label="-- %%INSERT_APP_NAME%% --"
android:requestLegacyExternalStorage="true">
<activity
android:name="org.qtproject.qt.android.bindings.QtActivity"
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
android:label="-- %%INSERT_APP_NAME%% --"
android:launchMode="singleTop"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="-- %%INSERT_APP_LIB_NAME%% --" />
<meta-data
android:name="android.app.arguments"
android:value="-- %%INSERT_APP_ARGUMENTS%% --" />
<meta-data
android:name="android.app.extract_android_style"
android:value="minimal" />
</activity>
</application>
</manifest>

View File

@@ -1,12 +0,0 @@
import QtQuick 2.14
import QtQuick.Window 2.14
Image {
id: bubble
source: "Bluebubble.svg"
smooth: true
property real centerX
property real bubbleCenter
property real centerY
fillMode: Image.PreserveAspectFit
}

View File

@@ -0,0 +1,32 @@
cmake_minimum_required(VERSION 3.16)
project(accelbubble VERSION 0.1 LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 6.2 COMPONENTS Quick Sensors Svg Xml REQUIRED)
qt_add_executable(accelbubbleexample
main.cpp
MANUAL_FINALIZATION
)
set_target_properties(accelbubbleexample PROPERTIES
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist"
)
set_property(TARGET accelbubbleexample APPEND PROPERTY
QT_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android
)
qt_add_qml_module(accelbubbleexample
URI accelbubble
VERSION 1.0
QML_FILES main.qml
RESOURCES Bluebubble.svg
)
target_compile_definitions(accelbubbleexample
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(accelbubbleexample
PRIVATE Qt6::Quick Qt6::Sensors Qt6::Svg Qt6::Xml)
qt_finalize_executable(accelbubbleexample)

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>accelbubble</string>
<key>CFBundleExecutable</key>
<string>accelbubble</string>
<key>CFBundleGetInfoString</key>
<string>Created by Qt</string>
<key>CFBundleIdentifier</key>
<string>io.qt.accelbubble</string>
<key>CFBundleName</key>
<string>accelbubble</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NOTE</key>
<string>This file was generated by Qt.</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
</dict>
</plist>

View File

@@ -1,25 +0,0 @@
QT += quick sensors svg xml
CONFIG += c++11
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
ANDROID_ABIS = armeabi-v7a

View File

@@ -1,14 +1,13 @@
#include <QGuiApplication> #include <QGuiApplication>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
QQmlApplicationEngine engine; QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml")); const QUrl url(u"qrc:/accelbubble/main.qml"_qs);
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) { &app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl) if (!obj && url == objUrl)

View File

@@ -1,49 +1,22 @@
import QtQuick 2.14 import QtQuick
import QtQuick.Window 2.14 import QtSensors
import QtSensors 5.12
Window { Window {
id: window
visible: true
property alias mainWindow: mainWindow
property alias bubble: bubble
Rectangle {
id: mainWindow id: mainWindow
color: "#ffffff" width: 320
anchors.fill: parent height: 480
visible: true
Bubble { title: qsTr("Accelerate Bubble")
id: bubble readonly property double radians_to_degrees: 180 / Math.PI
x: bubble.centerX - bubbleCenter
y: bubble.centerY - bubbleCenter
bubbleCenter: bubble.width /2
centerX: mainWindow.width /2
centerY: mainWindow.height /2
Behavior on y {
SmoothedAnimation {
easing.type: Easing.Linear
duration: 100
}
}
Behavior on x {
SmoothedAnimation {
easing.type: Easing.Linear
duration: 100
}
}
}
}
Accelerometer { Accelerometer {
id: accel id: accel
dataRate: 100 dataRate: 100
active:true active:true
readonly property double radians_to_degrees: 180 / Math.PI
onReadingChanged: { onReadingChanged: {
var newX = (bubble.x + calcRoll(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1) var newX = (bubble.x + calcRoll(accel.reading.x, accel.reading.y, accel.reading.z) * .1)
var newY = (bubble.y - calcPitch(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) * .1)
if (isNaN(newX) || isNaN(newY)) if (isNaN(newX) || isNaN(newY))
return; return;
@@ -66,9 +39,33 @@ Window {
} }
function calcPitch(x,y,z) { function calcPitch(x,y,z) {
return -Math.atan2(y, Math.hypot(x, z)) * accel.radians_to_degrees; return -Math.atan2(y, Math.hypot(x, z)) * mainWindow.radians_to_degrees;
} }
function calcRoll(x,y,z) { function calcRoll(x,y,z) {
return -Math.atan2(x, Math.hypot(y, z)) * accel.radians_to_degrees; return -Math.atan2(x, Math.hypot(y, z)) * mainWindow.radians_to_degrees;
}
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
}
}
} }
} }

View File

@@ -1,7 +0,0 @@
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>Bluebubble.svg</file>
<file>Bubble.qml</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -36,19 +36,21 @@
\title Creating a Mobile Application \title Creating a Mobile Application
This tutorial describes developing Qt Quick applications for Android and iOS This tutorial describes how to use \QC to develop Qt Quick applications for
devices using Qt Quick Controls. Android and iOS devices when using Qt 6 as the minimum Qt version and CMake
We use \QC to implement a Qt Quick application as the build system.
that accelerates an SVG (Scalable Vector Graphics) image based on the
changing accelerometer values. We implement a Qt Quick application that accelerates an SVG (Scalable Vector
Graphics) image based on the changing accelerometer values.
\note You must have the \l{Qt Sensors} module from Qt 6.2 or later installed
to be able to follow this tutorial.
\image creator_android_tutorial_ex_app.png \image creator_android_tutorial_ex_app.png
For more information about the UI choices you have, see \l{User Interfaces}.
\section1 Setting up the Development Environment \section1 Setting up the Development Environment
To be able to build the application for and run it on a mobile device, you must To build the application for and run it on a mobile device, you must
set up the development environment for the device platform and configure a set up the development environment for the device platform and configure a
connection between \QC and the mobile device. connection between \QC and the mobile device.
@@ -63,163 +65,58 @@
\include qtquick-tutorial-create-empty-project.qdocinc qtquick empty application \include qtquick-tutorial-create-empty-project.qdocinc qtquick empty application
\section1 Creating the Accelbubble Main View \section1 Adding Images as Resources
The main view of the application displays an SVG bubble image that moves The main view of the application displays an SVG bubble image that moves
around the screen when you tilt the device. around the screen when you tilt the device.
We use \e {Bluebubble.svg} in this tutorial, but you can use any other We use \e {Bluebubble.svg} in this tutorial, but you can use any other
image or component, instead. image or component instead.
To create the UI in \l{Form Editor}: For the image to appear when you run the application, you must specify it
as a resource in the \c RESOURCES section of \e CMakeLists.txt file that
the wizard created for you:
\list 1 \quotefromfile accelbubble/CMakeLists.txt
\skipto qt_add_qml_module
\printuntil )
\li Open the \e main.qml in \uicontrol {Form Editor}. \section1 Creating the Accelbubble Main View
\li In \l Library > \uicontrol Components > We create the main view in the \e main.qml file by adding an \l Image
\uicontrol {Default Components} > \uicontrol Basic, select component with \e Bluebubble.svg as the source:
\uicontrol Rectangle and drag-and-drop it to \e Window
in \l Navigator.
\li Select the rectangle instance in \uicontrol Navigator to edit its \quotefromfile accelbubble/main.qml
properties in \l Properties: \skipto Image
\printuntil smooth
\image qtquick-mobile-app-tutorial-main-view.png "Rectangle in different views" Next, we add custom properties to position the image in respect to the width
and height of the main window:
\list a \printuntil y:
\li In the \uicontrol ID field enter \e mainWindow, to be able
to reference the rectangle from other places.
\li Select the \uicontrol Layout tab, and then click
the \inlineimage icons/anchor-fill.png
(\uicontrol {Fill to Parent}) button to anchor the rectangle
to the window.
\endlist
\li Select \uicontrol Library > \uicontrol Assets >
\inlineimage plus.png
to locate Bluebubble.svg (or your own image) and add it to
the project folder.
\li Drag and drop the image from \uicontrol Assets to
\e mainWindow in \uicontrol Navigator. \QC creates an
instance of an \l{Images}{Image} component for you
with the path to the image file set as the value of
the \uicontrol Source field in \uicontrol Properties.
\li In the \uicontrol Properties view, \uicontrol ID field, enter
\e bubble to be able to reference the image from other places.
\image qtquick-mobile-app-tutorial-image.png "Image file in different views"
\li Select the \inlineimage icons/alias.png
(\uicontrol Export) button in \uicontrol Navigator to export
\e mainWindow and \e bubble as properties.
\endlist
We want to modify the properties of the bubble in ways that are not
supported in \uicontrol {Form Editor}, and therefore we turn it into
a custom component:
\list 1
\li Right-click the image and select
\uicontrol {Move Component into Separate File}.
\image qtquick-mobile-app-tutorial-bubble-component.png
\li In the \uicontrol {Component name} field, enter \e Bubble.
\li Deselect the \uicontrol x and \uicontrol y check boxes,
because we want to use the accelerometer to determine
the location of the bubble on the screen.
\li Select \uicontrol OK to create \e Bubble.qml.
\endlist
\QC creates an instance of the Bubble component in \e main.qml.
To check your code, you can compare your \e main.qml and
\e {Bubble.qml} with the corresponding example files.
The UI is now ready and you can add the necessary properties for
making the bubble move.
\section1 Moving the Bubble
We add custom properties to position the image in respect to the width
and height of the main window.
\list 1
\li Open \e Bubble.qml in \uicontrol {Form Editor}.
\li In \l {Connection View} > \uicontrol Properties,
select the \inlineimage plus.png
button to add a custom property for the Bubble component.
\image qtquick-mobile-app-tutorial-custom-properties.png "Connection View Properties tab"
\li Double-click the value in the \uicontrol Property column, and enter
\e centerY as the name of the property.
\li Double-click the value in the \uicontrol {Property Type} column,
and select \e real as the component of the property. You will specify
the property value later in \uicontrol Properties.
\li Add two more properties of the same type with the names \e centerY
and \e bubbleCenter.
\li Open \e main.qml in \uicontrol {Form Editor}.
\li Select \e bubble in \uicontrol Navigator to specify values for the
custom properties in \uicontrol Properties.
\li In the \uicontrol X field, select \inlineimage icons/action-icon.png
, and then select \uicontrol {Set Binding} to open
\uicontrol {Binding Editor}.
\image qtquick-mobile-app-tutorial-binding-editor1.png "Setting binding for X in Binding Editor"
\li Enter the following value to center the bubble horizontally in the
main window when the application starts:
\c{bubble.centerX - bubbleCenter}.
\li Select \uicontrol OK to close the binding editor and save the
binding.
\li In the \uicontrol X field, set the following binding to center the
bubble vertically: \c{bubble.centerY - bubbleCenter}.
\li In the \uicontrol centerY field, enter the following value to bind
the y coordinate of the bubble center to half the height of the main
window: \c {mainWindow.height /2}.
\image qtquick-mobile-app-tutorial-binding-editor.png "Setting binding for centerX"
\li In the \uicontrol centerX field, bind the x coordinate of
the bubble center to half the width of the main window:
\c {mainWindow.width /2}.
\li In the \uicontrol bubbleCenter field, bind the center of
the bubble to half of its width: \c {bubble.width /2}.
\endlist
We now want to add code to move the bubble based on Accelerometer sensor We now want to add code to move the bubble based on Accelerometer sensor
values. This is not supported by \l {Form Editor}, so we will do values. First, we add the following import statement:
it in \l {Text Editor}:
\list 1
\li Add the following import statement to \e main.qml:
\quotefromfile accelbubble/main.qml \quotefromfile accelbubble/main.qml
\skipto QtSensors \skipto QtSensors
\printline QtSensors \printline QtSensors
\li Add the \l{Accelerometer} component with the necessary properties: Next, we add the \l{Accelerometer} component with the necessary properties:
\skipto Accelerometer \skipto Accelerometer
\printuntil radians_to_degrees \printuntil active
\skipto }
\printuntil }
\li Add the following JavaScript functions that calculate the Then, we add the following JavaScript functions that calculate the
x and y position of the bubble based on the current Accelerometer x and y position of the bubble based on the current Accelerometer
values: values:
\quotefromfile accelbubble/main.qml \quotefromfile accelbubble/main.qml
\skipto function \skipto function
\printuntil Math.atan2(x \printuntil }
\printuntil } \printuntil }
\li Add the following JavaScript code for \c onReadingChanged signal of We add the following JavaScript code for \c onReadingChanged signal of
Accelerometer component to make the bubble move when the Accelerometer Accelerometer component to make the bubble move when the Accelerometer
values change: values change:
@@ -231,7 +128,8 @@
within the bounds of the screen. If the Accelerometer returns within the bounds of the screen. If the Accelerometer returns
\e {not a number} (NaN), the value is ignored and the bubble \e {not a number} (NaN), the value is ignored and the bubble
position is not updated. position is not updated.
\li Add \l SmoothedAnimation behavior on the \c x and \c y properties of
We add \l SmoothedAnimation behavior on the \c x and \c y properties of
the bubble to make its movement look smoother. the bubble to make its movement look smoother.
\quotefromfile accelbubble/main.qml \quotefromfile accelbubble/main.qml
@@ -239,7 +137,6 @@
\printuntil x \printuntil x
\printuntil } \printuntil }
\printuntil } \printuntil }
\endlist
\section1 Locking Device Orientation \section1 Locking Device Orientation
@@ -248,35 +145,69 @@
better for the screen orientation to be fixed. better for the screen orientation to be fixed.
To lock the orientation to portrait or landscape on Android, specify it in To lock the orientation to portrait or landscape on Android, specify it in
an AndroidManifest.xml that you can generate in \QC. For more information, an \e AndroidManifest.xml that you can generate in \QC. For more information,
see \l{Editing Manifest Files}. see \l{Editing Manifest Files}.
On iOS, you can lock the device orientation in an Info.plist file that you \image qtquick-mobile-tutorial-manifest.png "Accelbubble manifest file"
specify in the .pro file as the value of the QMAKE_INFO_PLIST variable.
To generate and use a manifest file, you must specify the Android package
source directory, \c QT_ANDROID_PACKAGE_SOURCE_DIR in the \e CMakeLists.txt
file:
\quotefromfile accelbubble/CMakeLists.txt
\skipto set_property
\printuntil )
Because our CMake version is older than 3.19, we must add a manual
finalization step to the \c qt_add_executable function:
\quotefromfile accelbubble/CMakeLists.txt
\skipto qt_add_executable
\printuntil )
We also need to add the \c qt_finalize_executable function:
\skipto qt_finalize_executable
\printuntil )
On iOS, you can lock the device orientation in an \e Info.plist file
that you specify in the \e CMakeLists.txt file as the value of the
\c MACOSX_BUNDLE_INFO_PLIST variable:
\quotefromfile accelbubble/CMakeLists.txt
\skipto set_target_properties
\printuntil )
\section1 Adding Dependencies \section1 Adding Dependencies
Update the accelbubble.pro file with the following library dependency You must tell the build system which Qt modules your application needs by
information: specifying dependencies in the project file. Select \uicontrol Projects to
update the CMake configuration with the following Qt module information:
\c Sensors, \c Svg, \c Xml.
\code The \e CMakeLists.txt file should contain the following entries that tell
QT += quick sensors svg xml CMake to look up the Qt installation and import the Qt Sensors, Qt SVG,
\endcode and Qt XML modules needed by the application:
On iOS, you must link to the above libraries statically, by adding the \quotefromfile accelbubble/CMakeLists.txt
plugin names explicitly as values of the QTPLUGIN variable. Specify a \skipto find_package
qmake scope for iOS builds (which can also contain the QMAKE_INFO_PLIST \printuntil REQUIRED
variable):
\code You also need to add the Qt modules to the list of target link libraries.
ios { \c target_link_libraries tells CMake that the accelbubble executable uses
QTPLUGIN += qsvg qsvgicon qtsensors_ios the Qt Sensors, Qt SVG, and Qt XML modules by referencing the targets
QMAKE_INFO_PLIST = Info.plist imported by the \c find_package() call above. This adds the necessary
} arguments to the linker and makes sure that the appropriate include
\endcode directories and compiler definitions are passed to the C++ compiler.
After adding the dependencies, select \uicontrol Build > \uicontrol {Run qmake} to apply \skipto target_link_libraries(accelbubble
the changes to the Makefile of the project. \printuntil Qt6
After adding the dependencies, select \uicontrol Build >
\uicontrol {Run CMake} to apply configuration changes.
For more information about the CMakeLists.txt file, see
\l{Get started with CMake}.
\section1 Running the Application \section1 Running the Application
@@ -292,7 +223,7 @@
If you are using a device running Android v4.2.2, it should prompt you to 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 verify the connection to allow USB debugging from the PC it is connected
to. To avoid such prompts every time you connect the device, select the to. To avoid such prompts every time you connect the device, select the
\uicontrol {Always allow from the computer} check box, and then select \uicontrol {Always allow from this computer} check box, and then select
\uicontrol OK. \uicontrol OK.
\li To run the application on the device, press \key {Ctrl+R}. \li To run the application on the device, press \key {Ctrl+R}.