1. Overview of Qt Embedded Development
Qt/Embedded Linux (now known as Qt for Device Creation) is a version of Qt optimized for embedded systems, featuring the following characteristics:
- No need for the X Window System, using its own window system QWS (Qt Window System)
- Customizable compilation, removing unnecessary modules
- Supports multiple processor architectures (ARM, MIPS, PowerPC, etc.)
- Provides a complete Qt API, compatible with the desktop version
1.1 Basic Environment Configuration
# Configure Qt for Embedded Linux
./configure -embedded <arch> -qt-gfx-linuxfb -no-largefile -no-opengl \
-qt-mouse-<mouse_driver> -qt-kbd-<keyboard_driver>
# Example: ARM architecture configuration
./configure -embedded arm -xplatform qws/linux-arm-g++ -qt-gfx-linuxfb \
-qt-mouse-tslib -qt-kbd-tty
2. Embedded Graphics System
2.1 Using Linux Framebuffer
// main.cpp
#include <QApplication>
#include <QLabel>
int main(int argc, char *argv[])
{
// Specify to use Linux framebuffer
QApplication app(argc, argv, QApplication::GuiServer);
QLabel label("Hello Embedded Qt!", 0);
label.setAlignment(Qt::AlignCenter);
label.resize(240, 320); // Typical embedded device resolution
label.show();
return app.exec();
}
2.2 Touchscreen Support (Using tslib)
// Initialize touchscreen
#include <tslib.h>
void initTouchScreen()
{
struct tsdev *ts = ts_setup(NULL, 0);
if (!ts) {
qWarning("Cannot initialize touchscreen");
return;
}
// Calibrate touchscreen (usually performed on first run)
if (access("/etc/pointercal", F_OK) != 0) {
QProcess::execute("ts_calibrate");
}
// Set Qt environment variable
qputenv("QWS_MOUSE_PROTO", "Tslib:/dev/input/event0");
}
3. Resource Optimization Techniques
3.1 Using Resource Files
// Compile-time resource file
// resources.qrc
<RCC>
<qresource prefix="/">
<file>images/logo.png</file>
<file>translations/app_zh.qm</file>
</qresource>
</RCC>
// Use resources in code
QPixmap pix(":/images/logo.png");
3.2 Static Compilation
# Static compile Qt library
./configure -static -release -no-exceptions -no-stl ...
# Static link application
qmake -config static
4. Embedded Input Methods
4.1 Virtual Keyboard Implementation
// virtualkeyboard.h
#include <QWidget>
#include <QSignalMapper>
class VirtualKeyboard : public QWidget
{
Q_OBJECT
public:
VirtualKeyboard(QWidget *parent = nullptr);
signals:
void keyPressed(const QString &text);
private:
QSignalMapper *mapper;
void createLayout();
};
// virtualkeyboard.cpp
VirtualKeyboard::VirtualKeyboard(QWidget *parent)
: QWidget(parent), mapper(new QSignalMapper(this))
{
createLayout();
connect(mapper, SIGNAL(mappedString(const QString&)),
this, SIGNAL(keyPressed(const QString&)));
}
void VirtualKeyboard::createLayout()
{
QGridLayout *layout = new QGridLayout(this);
const QStringList keys = {
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
"Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",
"A", "S", "D", "F", "G", "H", "J", "K", "L", ";",
"Z", "X", "C", "V", "B", "N", "M", ",", ".", "/"
};
for (int i = 0; i < keys.size(); ++i) {
QPushButton *btn = new QPushButton(keys[i]);
btn->setFixedSize(30, 30);
connect(btn, SIGNAL(clicked()), mapper, SLOT(map()));
mapper->setMapping(btn, keys[i]);
layout->addWidget(btn, i / 10, i % 10);
}
setLayout(layout);
}
5. Integration of Embedded Device Features
5.1 Power Management
#include <QPowerSource>
#include <QBatteryInfo>
class PowerMonitor : public QObject
{
Q_OBJECT
public:
PowerMonitor(QObject *parent = nullptr) : QObject(parent) {
QBatteryInfo battery;
connect(&battery, SIGNAL(remainingCapacityChanged(int,int)),
this, SLOT(updateBatteryStatus(int,int)));
QPowerSource *ac = new QPowerSource(QPowerSource::AC, this);
connect(ac, SIGNAL(availabilityChanged(bool)),
this, SLOT(onACStatusChanged(bool)));
}
public slots:
void updateBatteryStatus(int remaining, int max) {
int percent = (remaining * 100) / max;
qDebug() << "Battery:" << percent << "%";
if (percent < 10) {
emit lowBatteryWarning();
}
}
void onACStatusChanged(bool available) {
qDebug() << "AC power:" << (available ? "connected" : "disconnected");
}
signals:
void lowBatteryWarning();
};
5.2 Backlight Control
// Control LCD backlight brightness
void setBacklightBrightness(int percent)
{
QFile file("/sys/class/backlight/backlight/brightness");
if (file.open(QIODevice::WriteOnly)) {
int value = (percent * 255) / 100;
file.write(QByteArray::number(value));
file.close();
}
}
6. Embedded Deployment
6.1 Creating Root Filesystem
# Example deployment script
#!/bin/sh
QT_DIR=/opt/qt-embedded
APP_DIR=/opt/myapp
# Create target directory structure
mkdir -p $APP_DIR/{bin,lib,plugins}
# Copy application
cp myapp $APP_DIR/bin/
# Copy Qt libraries
cp $QT_DIR/lib/libQtCore.so.4 $APP_DIR/lib/
cp $QT_DIR/lib/libQtGui.so.4 $APP_DIR/lib/
# Copy plugins
cp -r $QT_DIR/plugins/{imageformats,sqldrivers} $APP_DIR/plugins/
# Create startup script
echo "#!/bin/sh\nexport QTDIR=$QT_DIR\nexport LD_LIBRARY_PATH=$APP_DIR/lib\nexport QT_PLUGIN_PATH=$APP_DIR/plugins\n$APP_DIR/bin/myapp -qws" > $APP_DIR/start_app.sh
chmod +x $APP_DIR/start_app.sh
6.2 Cross-Compilation Configuration
# myapp.pro cross-compilation configuration example
TARGET = myapp
# Specify cross-compiler
QMAKE_CC = arm-linux-gcc
QMAKE_CXX = arm-linux-g++
QMAKE_LINK = arm-linux-g++
# Embedded platform configuration
QT += core gui
QT_CONFIG -= opengl
# Optimization options
QMAKE_CFLAGS_RELEASE += -Os
QMAKE_CXXFLAGS_RELEASE += -Os
# Reduce executable size
QMAKE_LFLAGS += -Wl,-s
SOURCES += main.cpp \
# Other source files
HEADERS += # Header files
7. Qtopia Application Example
Qtopia is an embedded application framework built on Qt/Embedded.
7.1 Simple Qtopia Application
// qtopiaapp.cpp
#include <QtopiaApplication>
#include <QMainWindow>
#include <QSoftMenuBar>
class MyApp : public QMainWindow
{
Q_OBJECT
public:
MyApp(QWidget *parent = nullptr) : QMainWindow(parent) {
// Set Qtopia application window properties
setWindowTitle(tr("My Qtopia App"));
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
// Add soft menu
QSoftMenuBar::setLabel(this, Qt::Key_Select, tr("Select"));
QSoftMenuBar::addMenuTo(this, tr("Options"));
// Main interface content
QLabel *label = new QLabel(tr("Welcome to Qtopia!"), this);
label->setAlignment(Qt::AlignCenter);
setCentralWidget(label);
}
};
QTOPIA_ADD_APPLICATION("myapp", MyApp)
QTOPIA_MAIN
8. Performance Optimization Techniques
8.1 Reducing Memory Usage
// Load images using shared memory
QPixmap loadSharedPixmap(const QString &path)
{
static QHash<QString, QPixmap> pixmapCache;
if (!pixmapCache.contains(path)) {
QPixmap pix;
if (!pix.load(path)) {
qWarning() << "Failed to load image:" << path;
return QPixmap();
}
// Convert to the same format as the screen to reduce runtime conversion
pix = pix.convertToFormat(QImage::Format_RGB16);
pixmapCache.insert(path, pix);
}
return pixmapCache.value(path);
}
8.2 Optimizing Drawing Performance
// Optimized drawing for custom widgets
void CustomWidget::paintEvent(QPaintEvent *)
{
// 1. Use local drawing to avoid full-screen redraw
QPainter painter(this);
painter.setClipRect(dirtyRect);
// 2. Use pre-generated resources
static QPixmap cachedBackground = generateBackground();
painter.drawPixmap(0, 0, cachedBackground);
// 3. Disable anti-aliasing
painter.setRenderHint(QPainter::Antialiasing, false);
// 4. Use fast drawing methods
painter.drawRects(rects.data(), rects.size());
}
9. Embedded Debugging Techniques
9.1 Remote Debugging
// Use QtRemoteObjects for remote debugging
// Run on target device:
// myapp -qws -remote-debug 1234
// Connect on development machine:
void connectToRemoteDevice()
{
QRemoteObjectHost srcNode(QUrl("tcp://192.168.1.100:1234"));
// Get remote object
RemoteDebugInterface *debug = srcNode.acquire<RemoteDebugInterface>();
if (debug) {
connect(debug, &RemoteDebugInterface::logMessage,
[](const QString &msg) {
qDebug() << "Remote Log:" << msg;
});
}
}
9.2 Memory Monitoring
#include <QMemoryInfo>
void checkMemoryUsage()
{
QMemoryInfo memory;
qDebug() << "Memory usage:"
<< "\nTotal:" << memory.total() / 1024 << "KB"
<< "\nUsed:" << memory.used() / 1024 << "KB"
<< "\nFree:" << memory.free() / 1024 << "KB"
<< "\nApplication:" << memory.processUsed() / 1024 << "KB";
if (memory.free() < (2 * 1024 * 1024)) { // Less than 2MB
emit lowMemoryWarning();
}
}
Conclusion
Qt embedded development requires special attention to the following aspects:
- Resource Optimization: Streamlining the Qt library, static compilation, optimizing memory usage
- Input Methods: Adapting to touchscreen and small keyboard input
- Device Integration: Power management, backlight control, and other hardware features
- Performance Tuning: Optimizing drawing performance, reducing CPU and memory usage
- Deployment Strategies: Creating a compact filesystem, cross-compilation configuration
Qt for Device Creation provides a complete toolchain and API, enabling developers to create feature-rich and efficient applications for embedded devices. By effectively utilizing Qt’s cross-platform features and embedded optimization capabilities, the complexity of embedded development can be significantly reduced.