A simple understanding of qt, QML, cmake

vishnumuthu Avatar

About the author


MenuBar

 

A simple understanding of qt, QML, cmake

The Example qt_qml_cmake_pipe github link, Create a simple working for qt qml with cmake to show the working of QProperty.

* This is a simple example to set up communication between qt6 and qml.

* The example has simple Qml Rectangle, Text, TextField and Button.

* The example also show how the QProperty READ, WRITE and NOTIFY works.

C++ is a versatile and powerful programming language widely used for system software, game development, real-time simulations, and large-scale applications. Its object-oriented features make it ideal for writing efficient and high-performance applications.

CMake is a cross-platform build system generator that helps manage and control the build process of software projects written in C++, and other languages. It allows developers to define build processes in a platform-independent manner, generating native build configurations for compilers like Make, Ninja, or MSVC.

QML (Qt Modeling Language) is a declarative language used primarily for designing user interfaces in Qt applications. It enables the creation of dynamic, fluid, and highly customizable UIs with ease. QML, together with C++, is commonly used in modern GUI-based applications to combine robust backend logic with sleek, responsive front-end designs.

In Qt, the Q_PROPERTY macro is used to declare properties of a class that can be accessed by Qt’s meta-object system, making them available to QML or other parts of the Qt framework for binding, signaling, and other features. This macro allows properties to be readable, writable, and notifyable for changes.

Components:

READ: Specifies the function to read the property’s value (getter).

WRITE: Specifies the function to set or modify the property’s value (setter).

NOTIFY: Specifies a signal that is emitted when the property value changes.

// pipe.h
class Pipe : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    // the NOTIFY property calls the READ function when triggered and the
    // WRITE function send the data from qml to cpp code.
    Q_PROPERTY(int data_1 READ getdata_1 WRITE setData_1 NOTIFY data_1Changed FINAL)
    Q_PROPERTY(int data_2 READ getdata_2 WRITE setData_2 NOTIFY data_2Changed FINAL)

public:
    explicit Pipe(QObject *parent = nullptr);

    int getdata_1();
    void setData_1(int value);

    int getdata_2();
    void setData_2(int value);

signals:
    void data_1Changed();
    void data_2Changed();

private:
    int data_1, data_2;
};

Explanation:

READ: The getter getdata_1() is called to retrieve the value of data_1.

WRITE: The setter setData_1() is used to change the value of data_1. It ensures that changes are tracked, and the signal is emitted only when the value actually changes.

NOTIFY: The signal data_1Changed() is emitted when the property is updated, allowing other parts of the application (such as UI bindings in QML) to react to the change.

This mechanism is essential for data binding and interaction between the backend (C++) and the front-end (QML) in Qt applications.

// pipe.cpp
Pipe::Pipe(QObject *parent)
    : QObject{parent}
{
    data_1 = 0;
    data_2 = 0;
}

int Pipe::getdata_1()
{
    return data_1;
}

void Pipe::setData_1(int value)
{
    std::cout << "Data: " << value << std::endl;
    data_1 = value;
    data_1++;

    // emit data_1Changed(); // Block the NOTIFY property calls the READ function when triggered
}

int Pipe::getdata_2()
{
    return data_2;
}

void Pipe::setData_2(int value)
{
    std::cout << "Data: " << value << std::endl;
    data_2 = value;
    data_2++;

    emit data_2Changed(); // the NOTIFY property calls the READ function when triggered
}

QML part below:

//Main.qml
import QtQuick
import QtQuick.Controls
import qml_pipe

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("QML Pipe Example")

    // Fixed size
    maximumHeight: height
    maximumWidth: width
    minimumHeight: height
    minimumWidth: width

    Pipe{
        id : process
    }

    Rectangle{
        id: left_side
        anchors.left: parent.left
        width: parent.width / 2
        height: parent.height
        color: "orange"

        TextField{
            id: left_field
            x: 0
            y: 0
            width: parent.width
            height: 40
        }

        Button{
            id: left_click
            x : 0
            y : 50
            text: "Button_1"
            width: parent.width
            height: 40
            onClicked: process.data_1 = left_field.text
        }

        Text {
            id: left_text
            x : 0
            y : 100
            width: parent.width
            height: 40
            text: process.data_1
            font.family: "Helvetica"
            font.pointSize: 12
            color: "black"
            horizontalAlignment: Text.AlignHCenter
            verticalAlignment: Text.AlignVCenter
        }
    }

    Rectangle{
        id: right_side
        anchors.right: parent.right

        width: parent.width / 2
        height: parent.height
        color: "green"

        TextField{
            id: right_field
            x: 0
            y: 0
            width: parent.width
            height: 40
        }

        Button{
            id: right_click
            x : 0
            y : 50
            text: "Button_2"
            width: parent.width
            height: 40
            onClicked: process.data_2 = right_field.text
        }

        Text {
            id: right_text
            x : 0
            y : 100
            width: parent.width
            height: 40
            text: process.data_2
            font.family: "Helvetica"
            font.pointSize: 12
            color: "black"
            horizontalAlignment: Text.AlignHCenter
            verticalAlignment: Text.AlignVCenter
        }
    }
}

Explanation:

From QML, when the Button (right_click) is clicked the value in the TextField(right_field) is read and send to the cpp data_2. Here, there is a simple incremental part and emit is triggered to send the data back to Text(right_text). Also since the emit is commented in data_1, there is no change in lift side.

  

Comments

One response to “A simple understanding of qt, QML, cmake”

  1. […] on September 8, 2024Updated on September 8, 2024by vishnumuthuCategories:CPP Previous post: A simple understanding of qt, QML, cmake […]

Leave a Reply

Your email address will not be published. Required fields are marked *