Book Image

Hands-On Mobile and Embedded Development with Qt 5

By : Lorn Potter
Book Image

Hands-On Mobile and Embedded Development with Qt 5

By: Lorn Potter

Overview of this book

Qt is a world-class framework, helping you to develop rich graphical user interfaces (GUIs) and multi-platform applications that run on all major desktop platforms and most mobile or embedded platforms. The framework helps you connect the dots across platforms and between online and physical experience. This book will help you leverage the fully-featured Qt framework and its modular cross-platform library classes and intuitive APIs to develop applications for mobile, IoT, and industrial embedded systems. Considerations such as screen size, device orientation changes, and small memory will be discussed. We will focus on various core aspects of embedded and mobile systems, such as connectivity, networking, and sensors; there is no IoT without sensors. You will learn how to quickly design a flexible, fast, and responsive UI that looks great. Going further, you will implement different elements in a matter of minutes and synchronize the UI elements with the 3D assets with high precision. You will learn how to create high-performance embedded systems with 3D/2D user interfaces, and deploy and test on your target hardware. The book will explore several new features, including Qt for WebAssembly. At the end of this book, you will learn about creating a full software stack for embedded Linux systems using Yocto and Boot to Qt for Device Creation.
Table of Contents (23 chapters)
Title Page
Dedication
About Packt
Foreword
Contributors
Preface
Index

Going smaller, handling screen sizes


Porting applications which were developed for the desktop to run on smaller mobile devices can be a daunting task, depending on the application. Even creating new apps for mobiles, a few considerations need to be made, such as differences in screen resolution, memory constraints, and handling orientation changes. Touch screens add another fantastic way to offer touch gestures and can be challenging due to the differences in the size of a finger as point compared to a mouse pointer. Then there are sensors, GPS and networking to contemplate! 

Screen resolution

As you can see in the previous images in the Add QListView section, the application paradigms are fairly different between desktop and mobile phones. When you move to an even smaller display, things start to get tricky in regards to fitting everything on the screen.

Luckily, there are Qt Widgets that can help. The C++ classes QScrollArea, QStackedWidget and QTabbedWidget can show content more appropriately. Delegating your on-screen widgets to different pages will allow your users the same ease-of-navigation which a desktop application allows.

There might also be an issue on mobile devices while using QMenu. They can be long, unruly and have a menu tree that drills down too deeply for a small screen. Here's a menu which works well on a desktop:

On a mobile device, the last items on this menu become unreachable and unusable. We need to redesign this!

 

Menus can be fixed by eliminating them or refactoring them to reduce their depth, or by using something like a QStackedWidget to present the Menu options.

 

Qt has support for high (Dots Per InchDPI displays. Newer versions of Qt automatically compensate for differences between high DPI and low DPI displays for iOS and the Wayland display server protocol. For Android, the environmental variable QT_AUTO_SCALE_FACTOR needs to be set to true. To test different scale factors, set QT_SCALE_FACTOR, which works best with an integer, typically 1 or 2.

Let's run through a few examples of widgets and how they can be better used on differing screens:

  • Widgets like QScrollBar can be increased in size to better accommodate a finger as pointer, or better yet be hidden and use the widget itself to scroll. The UI usually needs to be simplified.
  • Long QListViews can present some challenges. You can try to filter or add a search feature for such long lists to make the data more accessible and eye pleasing on smaller displays.
  • Even QStackedWidget or QTabbedWidget can be too big. Don't make the user flick left or right more than a few pages. Anything more can be cumbersome and annoying for the user to be flicking endlessly to get at content.
  • QStyleSheets are a good way to scale for smaller display's, allowing the developer to specify customizations to any widget. You can increase the padding and margins to make it easier for finger touch input. You can either set a style on a specific widget or apply it to the entire QApplication for a certain class of widget.
qApp->setStyleSheet("QButton {padding: 10px;}");

or for one particular widget it would be:

myButton->setStyleSheet("padding: 10px;");

Let's apply this only when there is a touch screen available on the device. It will make the button slightly bigger and easier to hit with a finger:

if (!QTouchScreen::devices().isEmpty()) {
   qApp->setStyleSheet("QButton {padding: 10px;}");
}

Note

If you set one style with a style sheet, you will most likely need to customize the other properties and sub-controls as well. Applying one style sheet removes the default style.

Of course, it is also easy to set a style sheet in Qt Designer, just right click on the target widget and select, Change styleSheet from the context menu. As seen here on the Apple Mac:

Mobile phones and embedded devices have smaller displays, and they also have less RAM and storage.

Memory and storage

Mobile phones and embedded devices usually have less memory than desktop machines. Especially for embedded devices both RAM and storage are limited.

The amount of storage space used can be lowered by optimizing images, compressing if needed. If different screen sizes are not used, the images can by manually resized instead of scaling at runtime.

There are also heap vs stack considerations which generally always pass arguments into functions by reference by using the & (ampersand) operator. You will notice this in the majority of Qt code.

Compiler optimizations can greatly effect both performance and the size of executables. In general, Qt's qmake mkspec build files are fairly good at using the correct optimizations.

If storage space is a critical consideration, then building Qt yourself is a good idea. Configuring Qt using the -no-feature-* to configure out any Qt features you might not need is a good way to reduce it's footprint. For example, if a device has one static Ethernet cable connection and does not need network bearer management, simply configure Qt using -no-feature-bearermanagement. If you know you are not using SQL why ship those storage using libraries? Running configure with --list-features argument will list all the features available.

Orientation

Mobile devices move around (whodathunkit?) and sometimes it is better to view a particular app in landscape mode instead of portrait. On Android and iOS, responding to orientation changes are built in and occurs by default according to the users configuration. One thing you might need to do, is actually disable the orientation change. 

On iOS, you need to edit the plist.info file. For the key UISupportedInterfaceOrientations, you need to add the following:

<array><string>UIInterfaceOrientationLandscapeLeft</string></array>

On Android, edit the AndroidManifest.xml file android:screenOrientation="landscape"

If a picture frame device has a custom-built operating system, it might need it's photo viewing app to respond when the user switches orientations. That's where Qt Sensors can help out. More on that later in the first section of Chapter 7, Machines Talking.

Gestures

Touchscreen gestures are another way mobiles are different to desktops. Multi-touch screens have revolutionized the device world. QPanGesture, QPinchGesture and QSwipeGesturecan be used to great effect on these devices, and Qt Quick has components build for this type of thing—Flickable, SwipeView, PinchArea and others. More on Qt Quick later.

To use QGestures, first create a QList of containing the gestures you want to handle, and call the grabGesture function for the target widget.

QList<Qt::GestureType>gestures;
gestures<<Qt::PanGesture;
gestures<<Qt::PinchGesture;
gestures<<Qt::SwipeGesture;
for(Qt::GestureType gesture : gestures)
    someWidget->grabGesture(gesture);

You will need to derive from and then override the widgets event loop to handle when the event happens.

boolSomeWidget::event(QEvent*event)
{
if(event->type()==QEvent::Gesture)
return handleGesture(static_cast<QGestureEvent *>(event));
returnQWidget::event(event);
}

To do something useful with the gesture, we could handle it like this:

if(QGesture*swipe=event->gesture(Qt::SwipeGesture)) {
    if (swipe->state()==Qt::GestureFinished){
switch(gesture->horizontalDirection()) {
            case QSwipeGesture::Left:
            break;
            case QSwipeGesture::Right:
            break;
            case QSwipeGesture::Up:
            break;
            case QSwipeGesture::Down:
            break;
        }
    }
}

Devices with sensors also have access to QSensorGesture, which enable motion gestures such as shake. More on that later, in Chapter 7, Machines Talking.