Evgenii Legotckoi
Evgenii Legotckoi05 липня 2017 р. 06:05

QML - Підручник 029. Реєстрація об'єкта Singleton для використання "статичних" методів у QML

Поняття статичних методів, які використовуються в QML, дещо відрізняється від класичного в C++, коли в класі створюються статичні методи, які можна використовувати звертаючись до імені класу, а не до якогось конкретного об'єкта. У випадку з QML справи трохи інакше. Для того, щоб використовувати такі методи в QML, які присутні в класі C++, необхідно зареєструвати Сінглетон об'єкт, який надаватиме потрібні методи, причому ці методи вже не повинні бути статичними самі по собі. Вони повинні бути як мінімум позначені макросом Q_INVOKABLE , щоб їх можна було використовувати в QML.

Для реєстрації Синглетону необхідно використовувати функцію qmlRegisterSingletonType , в яку крім стандартних параметрів, що передаються qmlRegisterType , необхідно також передати статичну функцію singletonProvider , яку також потрібно написати самим.


Структура проекту

Створіть Qt Quick проект, який містить такі файли:

  • SingletonQMLCpp.pro - профайл проекту
  • main.cpp - файл з main функцією
  • main.qml - основний файл qml
  • singletonclass.h - заголовний файл синглетону
  • singletonclass.cpp - файл вихідних кодів синглетону

Профайл проекту буде створено за замовчуванням і не змінюватиметься.

main.cpp

Почнемо з файлу main.cpp, де зареєструємо об'єкт майбутнього синглетону.

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml> // Подключаем для использования qmlRegisterSingletonType

#include "singletonclass.h" // Подключаем заголовочный файл SingletonClass

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

    // регистрируем объект синглетона через функцию singletonProvider, то есть передаём указатель на неё в качестве аргумента.
    qmlRegisterSingletonType<SingletonClass>("SingletonClass", 1, 0, "SingletonClass", singletonProvider);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

singletonclass.h

У заголовному файлі визначимо enum , який будемо використовувати для отримання певних повідомлень через "статичний" метод getMessage у шарі QML. У цьому файлі визначимо статичну функцію singletonProvider , яка створювати інстанс синглетона.

#ifndef SINGLETONCLASS_H
#define SINGLETONCLASS_H

#include <QObject>
#include <QQmlEngine>
#include <QJSEngine>

class SingletonClass : public QObject
{
    Q_OBJECT
public:
    explicit SingletonClass(QObject *parent = nullptr);

    enum class Message {
        Info,
        Debug,
        Warning,
        Error
    };
    // Регистрация enum для испоьлзования в QML
    Q_ENUM(Message)

    // Чтобы использовать этот метод в QML, объявите его на Q_INVOKABLE
    Q_INVOKABLE QString getMessage(Message message);

signals:

public slots:
};

static QObject *singletonProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
{
    Q_UNUSED(engine)
    Q_UNUSED(scriptEngine)

    SingletonClass *singletonClass = new SingletonClass();
    return singletonClass;
}

#endif // SINGLETONCLASS_H

Зауважте, що getMessage не повинен бути статичним, щоб виступати як статичний метод Типу в QML.

singletonclass.cpp

У цьому файлі дана реалізація методу getMessage.

#include "singletonclass.h"

SingletonClass::SingletonClass(QObject *parent) : QObject(parent)
{

}

QString SingletonClass::getMessage(SingletonClass::Message message)
{
    switch (message)
    {
        case Message::Info:
            return "This is Info Message";
        case Message::Debug:
            return "This is Debug Message";
        case Message::Warning:
            return "This is Warning Message";
        case Message::Error:
            return "This is Error Message";
        default:
            return "Nothin not found";
    }
}

main.qml

А тепер скористаємося цим синглетоном типом в QML.

import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Controls 1.4

import SingletonClass 1.0 // Подключаем Синглетон


Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Singleton Class")

    ListView {
        anchors.fill: parent
        delegate: Item {
            height: 48
            width: parent.width
            Text {
                anchors.fill: parent
                text: model.text

                verticalAlignment: Text.AlignVCenter
                horizontalAlignment: Text.AlignHCenter
            }
        }

        model: listModel
    }

    ListModel {
        id: listModel

        // Нет возможности использовать методы и функции сразу для property в ListElement, поэтому использован такой хак
        Component.onCompleted: {
            listModel.append({'text': SingletonClass.getMessage(SingletonClass.Info)})
            listModel.append({'text': SingletonClass.getMessage(SingletonClass.Debug)})
            listModel.append({'text': SingletonClass.getMessage(SingletonClass.Warning)})
            listModel.append({'text': SingletonClass.getMessage(SingletonClass.Error)})
        }
    }
}

Підсумок

В результаті буде отримано програму, яка виведе чотири повідомлення у своєму вікні.

Таким чином через синглетон об'єкт у QML додається можливість використання cpp методів як статичні.

Завантажити архів з проектом

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

3
  • 01 жовтня 2018 р. 15:05

In the debugger, I could not manage to see if the constructor is called once for all or if is called at every occurence from QML. Do you know?

Evgenii Legotckoi
  • 05 жовтня 2018 р. 08:11

For QML constructor will be called once.

It works some differently from classic Singleton, but instance will be one.

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
Дмитрий

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:60бали,
  • Рейтинг балів-1
Дмитрий

C++ - Тест 003. Условия и циклы

  • Результат:92бали,
  • Рейтинг балів8
d
  • dsfs
  • 26 квітня 2024 р. 04:56

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80бали,
  • Рейтинг балів4
Останні коментарі
k
kmssr08 лютого 2024 р. 18:43
Qt Linux - Урок 001. Автозапуск програми Qt під Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко05 лютого 2024 р. 01:50
Qt WinAPI - Урок 007. Робота з ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 грудня 2023 р. 10:30
Boost - статичне зв&#39;язування в проекті CMake під Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 грудня 2023 р. 08:38
Boost - статичне зв&#39;язування в проекті CMake під Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
Gvozdik18 грудня 2023 р. 21:01
Qt/C++ - Урок 056. Підключення бібліотеки Boost в Qt для компіляторів MinGW і MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Тепер обговоріть на форумі
G
George1307 травня 2024 р. 00:27
добавить qlineseries в функции в функции: "GPlotter::addSeries(QString title, QVector &arr)" я вызываю метод setChart(...), я в конструктор передал адрес на QChartView элемент
BlinCT
BlinCT05 травня 2024 р. 05:46
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
PS
Peter Son03 травня 2024 р. 17:57
Best Indian Food Restaurant In Cincinnati OH Ready to embark on a gastronomic journey like no other? Join us at App india restaurant and discover why we're renowned as the Best Indian Food Restaurant In Cincinnati OH . Whether y…
Evgenii Legotckoi
Evgenii Legotckoi02 травня 2024 р. 14:07
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.
IscanderChe
IscanderChe30 квітня 2024 р. 04:22
Во Flask рендер шаблона не передаётся в браузер Доброе утро! Имеется вот такой шаблон: <!doctype html><html> <head> <title>{{ title }}</title> <link rel="stylesheet" href="{{ url_…

Слідкуйте за нами в соціальних мережах