یکی از مزایای توسعه اپلیکیشن با Qml، امکان ارتباط مستقیم بین کد Qml و ++C است. که باعث می شود بتوان به راحتی منطق برنامه را به رابط کاربری پیوند زد. هرچند می توان از کدهای جاوا اسکریپت (JavaScript) در برنامه های Qml استفاده کرد. ولی برای پردازش های سنگین، ارتباط با پایگاه داده، اتصال به شبکه و … گزینه بهتر ++C خواهد بود.

ارتباط بین کد ++C و Qml

به طور کلی می توان به دو روش بین رابط کاربری – ایجاد شده با Qml – و کد ++C ارتباط داشت. یکی با استفاده از rootContext موتور کیو ام ال (Qml) و دیگری با استفاده از ماژول ها. البته می توان از پلاگین (Plugin) هم استفاده کرد. روش پلاگین را در نوشته «پلاگین‌های QML» بررسی خواهیم کرد.

ارتباط Qml با ++C

استفاده از rootContext

در این روش ابتدا یک نمونه (Instance) از کلاسی که می خواهیم به کیو ام ال معرفی کنیم می سازیم. سپس آن را به rootContext موتور کیو ام ال معرفی می کنیم. حال در هر فایل qml در برنامه می توانیم آن را فراخوانی کنیم. نکته ای که باید به خاطر داشته باشید اینست که آبجکت (یا نمونه) معرفی شده بصورت یک مقدار Global در تمام فایل های برنامه در دسترس خواهد بود. همچنین کلاسی که معرفی می کنیم دارای شرایط خاصی است که در پایان همین نوشته به آن اشاره می کنیم.

این روش برای زمانی که می خواهیم یک مقدار Global معرفی کنیم مناسب است و امکان ساخت نمونه های دیگر از همان کلاس را نداریم. به عنوان مثال در تکه کد زیر یک نمونه از کلاس ControlBack به موتور کیو ام ال معرفی شده است.

//main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "controlback.h"

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

    ControlBack cb;
    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("controlBack", &cb);
    engine.load(QUrl(QStringLiteral("qrc:/QmlApp/main.qml")));

    return app.exec();
}

نخست کتابخانه QQmlContext را به کد وارد می کنیم (include). سپس یک نمونه از کلاس ControlBack بنام cb می سازیم و آن را با متد setContextProperty به نام “controlBack” به rootContext اضافه می کنیم.

//main.qml
import QtQuick
import QtQuick.Controls

Window {
    id: appRoot
    width: 400; height: 300
    visible: true
    title: qsTr("Qml and C++")
    
    Text { id: textId; text: "Information" }    
    Button {
        text: "Show"
        onClicked: { textId.text = controlBack.getInfo() }
    }
}

 برای فراخوانی این مقدار در qml فقط کافیست controlBack را فرخوانی کنیم. دقت کنید در این روش نیاز به import در qml نیست. به عنوان مثال در فایل main.qml بالا تابع getInfo را از کلاس ControlBack فراخوانی می کنیم.

ایجاد کلاس در ++C

همانطور که بالاتر گفتم، کلاس معرفی شده به کیو ام ال شرایط خاصی دارد. این کلاس حتما باید از کلاس  QObject مشتق شده باشد. البته می توان از هر کلاس دیگری که از QObect مشتق شده است نیز استفاده کرد. برای استفاده از سیگنال ها و اسلات ها نیز باید ماکرو Q_OBJECT را اضافه کنیم. هر مقداری که قرار است در کیو ام ال قابل دسترس باشد را با ماکرو Q_PROPERTY و متد ها را با Q_INVOKABLE معرفی می کنیم. همچنین متد های بخش public slots نیز در کیو ام ال در دسترس خواهند بود. در تکه کد زیر کلاس ControlBack  به عنوان نمونه آورده شده است.

//controlback.h
#ifndef CONTROLBACK_H
#define CONTROLBACK_H

#include <QObject>

class ControlBack : public QObject {
    Q_OBJECT
    Q_PROPERTY(int counter READ counter WRITE setCounter NOTIFY counterChanged FINAL)
public:
    explicit ControlBack(QObject *parent = nullptr);
    int counter();
    void setCounter(int cnt);
    Q_INVOKABLE QString getInfo();

signals:
    void counterChanged(int cnt);

private:
    int m_counter = 0;
};

#endif // CONTROLBACK_H
//controlback.cpp
#include "controlback.h"

ControlBack::ControlBack(QObject *parent)
    : QObject{parent} {}

int ControlBack::counter() {
    return m_counter;
}

void ControlBack::setCounter(int cnt) {
    m_counter = cnt;
    emit counterChanged(m_counter);
}

QString ControlBack::getInfo() {
    return QString("Some important information");
}

ماکرو Q_PROPERTY

در کلاس ControlBack ما فیلد counter را با استفاده از ماکروی Q_PROPERTY تعریف کرده ایم. این ماکرو چهار بخش دارد. در بخش اول نوع و نام فیلد را وارد می کنیم (int counter). بخش دوم متد خواندن فیلد را معرفی می کنیم (READ counter). این متد معمولا هم نام فیلد است و آن را در بخش public کلاس تعریف می کنیم. بخش سوم متد بازنویسی فیلد است ( WRITE setCounter). موتور کیو ام ال با استفاده از این متد مقدار فیلد را بروزرسانی می دهد. این متد را نیز در بخش public کلاس تعریف می کنیم. بخش چهارم سیگنال تغییر فیلد است (NOTIFY counterChanged). که هر زمان مقدار فیلد counter تغییر کند به موتور کیو ام ال اعلام می کند تا رابط کاربری را بروزرسانی کند. این سیگنال را در بخش signals کلاس تعریف می کنیم.

ماکرو Q_INVOKABLE

از ماکرو Q_INVOKABLE برای تعیین متد هایی استفاده می کنیم که می خواهیم در کیو ام ال در دسترس باشند. این متد ها می توانند دارای پارامتر و مقدار بازگشتی باشند. فراخوانی این متد ها در کیو ام ال نیز مانند سی پلاس پلاس (++C) است (به فایل main.qml در بالا نگاه کنید). 

استفاده از qmlRegisterType

متد qmlRegisterType از کلاس QQmlEngine برای معرفی یک کلاس ++C به موتور Qml بکار می‌رود. سپس می‌توان نمونه‌ای از آن کلاس را در فایل کیو ام ال ایجاد و استفاده کرد.

فرض کنید می‌خواهیم کلاس ControlBack بالا را در موتور کیو ام ال ثبت کنیم. فقط کافیست در فایل main.cpp خط زیر را اضافه کنیم:

qmlRegisterType<ControlBack>("ir.samiyacode.controlback", 1, 0, "ControlBack");

که در آن “ir.samiyacode.controlback” به عنوان URI کلاس (می‌تواند هر رشته‌ای باشد، فقط کافیست یک رشته یکتا در پروژه باشد)، اعداد 1 و 0 با هم سماره نسخه (Version 1.0) و “ControlBack” نامی که در Qml می‌خواهیم استفاده کنیم.

حالا در هر فایل کیو ام ال می‌توانیم این کلاس را import کنیم و بکار ببریم:

import ir.samiyacode.controlback 1.0
...
ControlBack {
    id: controlBackId
}
...

اگر از CMake برای ساخت پروژه‌تان استفاده می‌کنید، می‌توانید فایل‌های منبع کلاس را به بخش SOURCES در تابع qt_add_qml_mdule اضافه کنید. بدین ترتیب نیاز به اضافه کردن خط بالا به فایل main.cpp نخواهید داشت. زیرا qt_add_qml_module کار ثبت کلاس در موتور کیو ام ال را انجام می‌دهد. برای اطلاعات بیشتر به نوشته «ماژول های QML» مراجعه کنید.

استفاده از Qml Modules

روش دیگر برای ارتباط Qml با ++C، استفاده از ماژول های کیو ام ال (Qml Modules) است. این روش راه حل توصیه شده کیوت (Qt) است.

در این روش کلاس های ++C در موتور کیو ام ال ثبت (Register) می شوند. هر کلاس یک نوع (Type) را در کیو ام ال تعریف می کند. که می توان آن ها را در فایل های مختلف qml ایجاد و استفاده کرد. 

از آنجا که ماژول ها در کیو ام ال مبحث بزرگی را تشکیل می دهند. در نوشته «ماژول های QML» به آن ها خواهیم پرداخت.

وردل، یک بازی ساده و جذاب حدس کلمه است که امروزه طرفداران زیادی پیدا کرده است. هدف این بازی حدس زدن کلمه هدف با استفاده از راهنما های بازی است.

ارتباط Qml با ++C
Tagged on:             

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *