C
Qt Quick Ultralite instrument_cluster Example
Demonstrates how to control user interface elements from a C application.
Overview
This example demonstrates how to control user interface elements from a C application.
Target platforms
Project structure
The instrument_cluster
example consists of the following files:
src/VehicleStatus.cpp
src/VehicleStatus.h
CMakeLists.txt
mcu_instrument_cluster.qmlproject
instrument_cluster.qml
The CMake project file contains a basic build script, instrument_cluster.qml
which defines the application's UI. The project configuration is defined in mcu_instrument_cluster.qmlproject
.
In addition to these files, the src/simulation
folder contains a simple simulator to provide input data for the instrument cluster on non-AUTOSAR platforms:
src/simulation/baremetal/main.cpp
src/simulation/freertos/main.cpp
src/simulator.cpp
src/simulator.h
The fonts
folder contains the font files of the application:
fonts/TitilliumWeb-Light.ttf
fonts/TitilliumWeb-SemiBold.ttf
CMake project file
Note: Simulation files are added only for non-AUTOSAR targets.
cmake_minimum_required (VERSION 3.21.1) project(instrument_cluster VERSION 0.0.1 LANGUAGES C CXX ASM) if (NOT TARGET Qul::Core) find_package(Qul) endif() set(TARGET_SOURCES src/VehicleStatus.cpp) set(INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/src) set(GENERATE_ENTRYPOINT_ARG "") if(NOT QUL_PLATFORM MATCHES "autosar") set(SIMULATOR_DIR src/simulation) set(TARGET_SOURCES ${TARGET_SOURCES} ${SIMULATOR_DIR}/simulator.cpp ${SIMULATOR_DIR}/${QUL_OS_LOWERCASE}/main.cpp ) set(INCLUDE_DIRECTORIES ${INCLUDE_DIRECTORIES} ${CMAKE_CURRENT_SOURCE_DIR}/src/simulation ) else() set(GENERATE_ENTRYPOINT_ARG GENERATE_ENTRYPOINT) endif() qul_add_target(instrument_cluster ${TARGET_SOURCES} QML_PROJECT mcu_instrument_cluster.qmlproject ${GENERATE_ENTRYPOINT_ARG} ) app_target_setup_os(instrument_cluster) target_include_directories(instrument_cluster PRIVATE ${INCLUDE_DIRECTORIES} ) if(NOT CMAKE_CROSSCOMPILING AND NOT WIN32) add_custom_command(TARGET instrument_cluster COMMAND strip instrument_cluster -o instrument_cluster.stripped DEPENDS instrument_cluster) endif()
QmlProject file
import QmlProject 1.3 Project { mainFile: "instrument_cluster.qml" MCU.Config { defaultFontFamily: "Titillium Web" } FontFiles { files: [ "fonts/TitilliumWeb-Light.ttf", "fonts/TitilliumWeb-SemiBold.ttf" ] } QmlFiles { files: [ "instrument_cluster.qml" ] } InterfaceFiles { files: ["src/VehicleStatus.h"] } }
VehicleStatus singleton
The VehicleStatus
singleton is responsible for storing the vehicle parameters for the user interface. It inherits from Qul::Singleton to expose the public signals and properties to QML. It also inherits from Qul::EventQueue to provide an event queue to trigger user interface update when the property values are changed.
... Qul::Property<int> speed; Qul::Property<double> tripMeter; Qul::Signal<void(bool leftBlinkerState)> leftBlinkerStateChange; Qul::Signal<void(bool rightBlinkerState)> rightBlinkerStateChange; ...
The QML code accesses these values via VehicleStatus
singleton:
... Text { id: speedometer color: "#2CDE85" anchors.centerIn: parent font.weight: Font.DemiBold font.pixelSize: 90 text: VehicleStatus.speed } ...
The repainting of the instrument cluster is triggered by using a dummy event queue. Event handling requires Qt Quick Ultralite engine to do an update.
... void qul_application_send_value_change_event() { VehicleStatus::instance().postEvent(true); } ...
The actual event handler does nothing:
... void onEvent(const bool &value) { // Dummy event queue to trigger UI updates (void) value; } ...
C linkage functions are exposed to the non-GUI code to control instrument cluster content:
... extern "C" { void qul_application_set_speed(int speed) { VehicleStatus::instance().speed.setValue(speed); } ...
AUTOSAR example
In an AUTOSAR project, the Qt Quick Ultralite Complex Device Driver calls the C linkage APIs as shown below:
#include "VehicleStatus.h" ... // QUL Complex Device Driver Runnable with a periodic trigger void Cdd_Qul_Update(void) { int changedValuesCount = 0; static int previousSpeed = 0; int speed; // Read the speed value via the AUTOSAR Interface // Rte_Read_Cdd_Qul_Speed(&speed); if (speed != previousSpeed) { changedValuesCount++; qul_application_set_speed(speed); previousSpeed = speed; } ... if (changedValuesCount > 0) { // Send an event to trigger repainting of the UI qul_application_send_value_change_event(); } qul_update_engine(); // Calls Qul::Application::update() }
Files:
- instrument_cluster/CMakeLists.txt
- instrument_cluster/instrument_cluster.qml
- instrument_cluster/mcu_instrument_cluster.qmlproject
- instrument_cluster/src/VehicleStatus.cpp
- instrument_cluster/src/VehicleStatus.h
- instrument_cluster/src/simulation/baremetal/main.cpp
- instrument_cluster/src/simulation/simulator.cpp
- instrument_cluster/src/simulation/simulator.h
See also Integrating C++ code with QML.
Available under certain Qt licenses.
Find out more.