1. #!trpst#trp-gettext data-...
  2. #!trpst#trp-gettext data-...
  3. QT
  4. Qt Quick ve QML
  5. C++ ve QML Entegrasyonu: Q_PROPERTY ve contextProperty ile Veri Paylaşımı

C++ ve QML Entegrasyonu: Q_PROPERTY ve contextProperty ile Veri Paylaşımı

Print

Qt Quick ile proje geliştirirken en ideal mimari prensip: “Arayüz QML’de, İş Mantığı ve Donanım Erişimi C++’ta” kuralıdır. QML görsel akıcılıkta rakipsizken; yüksek hesaplama gücü, seri port/CAN bus donanım haberleşmesi ve veritabanı erişimi C++’ın uzmanlık alanıdır. Bu iki dünyayı birbirine bağlayan köprü olan C++ ve QML entegrasyonu, projenin performansını ve kod kalitesini belirleyen en kritik adımdır.

Bu rehberde; QPROPERTY makrosunun anatomisini, C++ sınıflarını QML motoruna tanıtmanın iki yolunu (setContextProperty ve qmlRegisterType), C++ metodlarını QML’den çağırmayı (QINVOKABLE) ve C++ sinyalleriyle QML arayüzünü anlık güncellemeyi inceleyeceğiz.


Entegrasyon Yöntemleri Karşılaştırması

C++ nesnelerini QML ile buluşturmanın iki ana yaklaşımı vardır:

YöntemAçıklamaKullanım Senaryosu
setContextPropertyTek bir C++ nesnesini global singleton gibi QML köküne enjekte eder.Genel Sistem Yöneticisi, Tekil Servisler (Backend Controller).
qmlRegisterTypeC++ sınıfını doğrudan yeni bir QML ögesi (etiket) gibi kaydeder.QML içinde birden fazla üretilebilen özel bileşenler.

Adım 1: C++ Backend Sınıfını Hazırlamak

Gelin bir donanım sensör yöneticisi tasarlayalım (SensorController). Bu sınıf sıcaklık değerini okusun, bir fanı açıp kapatsın ve QML arayüzüne anlık bildirim göndersin.

sensorcontroller.h

#ifndef SENSORCONTROLLER_H
#define SENSORCONTROLLER_H

#include <QObject>
#include <QTimer>

class SensorController : public QObject {
    Q_OBJECT

    // Q_PROPERTY ile C++ değişkenini QML'e tanıtıyoruz
    Q_PROPERTY(double temperature READ temperature NOTIFY temperatureChanged)
    Q_PROPERTY(bool fanRunning READ isFanRunning WRITE setFanRunning NOTIFY fanStatusChanged)

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

    double temperature() const { return m_temperature; }
    bool isFanRunning() const { return m_fanRunning; }

    // QML'den doğrudan çağrılabilen C++ metodu
    Q_INVOKABLE void emergencyStop();

public slots:
    void setFanRunning(bool running);

signals:
    void temperatureChanged(double newTemp);
    void fanStatusChanged(bool running);
    void alertTriggered(const QString &message);

private slots:
    void updateSensorData();

private:
    double m_temperature = 24.5;
    bool m_fanRunning = false;
    QTimer *m_timer = nullptr;
};

#endif // SENSORCONTROLLER_H

sensorcontroller.cpp

#include "sensorcontroller.h"
#include <QRandomGenerator>

SensorController::SensorController(QObject *parent) : QObject(parent) {
    // Sensör simülasyonu için timer
    m_timer = new QTimer(this);
    connect(m_timer, &QTimer::timeout, this, &SensorController::updateSensorData);
    m_timer->start(1000); // Her saniye oku
}

void SensorController::setFanRunning(bool running) {
    if (m_fanRunning == running) return;
    m_fanRunning = running;
    emit fanStatusChanged(m_fanRunning);
}

void SensorController::emergencyStop() {
    setFanRunning(false);
    emit alertTriggered("Acil Durum: Fanlar durduruldu!");
}

void SensorController::updateSensorData() {
    // Sıcaklığı rastgele dalgalandır
    double delta = (QRandomGenerator::global()->bounded(100) - 50) / 100.0;
    m_temperature += delta;
    emit temperatureChanged(m_temperature);

    // Eşik değer kontrolü
    if (m_temperature > 40.0 && !m_fanRunning) {
        setFanRunning(true);
        emit alertTriggered("Aşırı Isınma: Fan otomatik başlatıldı!");
    }
}

Önemli İpucu (QINVOKABLE): QML’den C++ fonksiyonu çağırmak istiyorsanız fonksiyonu ya public slots: altına koymalı ya da başına QINVOKABLE makrosu eklemelisiniz. Standart C++ fonksiyonları QML tarafından görülemez.


Adım 2: main.cpp İçinde QML’e Enjekte Etmek

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "sensorcontroller.h"

int main(int argc, char *argv[]) {
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    // C++ Backend nesnesini oluştur
    SensorController backend;

    // Yöntem 1: QML'e global erişilebilir 'backend' adıyla tanıt
    engine.rootContext()->setContextProperty("backend", &backend);

    // QML dosyasını yükle
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    engine.load(url);

    return app.exec();
}

Adım 3: QML Arayüzünde Kullanım

Artık main.qml dosyasında backend nesnesi sanki yerel bir QML ögesiymiş gibi davranır:

import QtQuick 2.15
import QtQuick.Controls 2.15

ApplicationWindow {
    visible: true
    width: 400
    height: 350
    title: "Sensör İzleme Paneli"
    color: "#2c3e50"

    Column {
        anchors.centerIn: parent
        spacing: 20

        // 1. C++'tan gelen canlı sıcaklık verisi (Otomatik Reaktif!)
        Text {
            anchors.horizontalCenter: parent.horizontalCenter
            text: backend.temperature.toFixed(1) + " °C"
            font.pixelSize: 42
            font.bold: true
            color: backend.temperature > 35.0 ? "#e74c3c" : "#2ecc71"
        }

        // 2. C++ fan durumu anahtarı
        Switch {
            anchors.horizontalCenter: parent.horizontalCenter
            text: "Soğutma Fanı"
            checked: backend.fanRunning
            onToggled: {
                // QML'den C++ setter fonksiyonunu tetikle
                backend.fanRunning = checked
            }
        }

        // 3. Q_INVOKABLE buton çağrısı
        Button {
            anchors.horizontalCenter: parent.horizontalCenter
            text: "Acil Durdurma"
            onClicked: {
                backend.emergencyStop()
            }
        }

        // 4. Uyarı mesajı alanı
        Text {
            id: alertLabel
            anchors.horizontalCenter: parent.horizontalCenter
            text: ""
            color: "#f39c12"
            font.pixelSize: 14
        }
    }

    // 5. C++ Sinyallerini Dinlemek: Connections Bileşeni
    Connections {
        target: backend
        function onAlertTriggered(message) {
            alertLabel.text = message
        }
    }
}

Özet

C++ ve QML birlikteliği, Qt platformunun en güçlü silahıdır. QPROPERTY ile iki yönlü reaktif veri akışını kurabilir, QINVOKABLE ile donanım ve iş mantığını tetikleyebilir ve Connections ile C++ sinyallerini akıcı görsel bildirimlere dönüştürebilirsiniz.

Tags , , , , ,

How can we help?