@PythonBeginner20

Как создать класс, расширяющий библиотеку C++ под QT для работы в QML?

Здравствуйте, вопрос звучит бредово, но не знаю как его описать грамотнее.

У меня есть файл mytcpserver.h
mytcpserver.h
#ifndef MYTCPSERVER_H
#define MYTCPSERVER_H

#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <iostream>
#include <QTime>
#include <QBasicTimer>
#include <QTimerEvent>
#include "judgementmodes.h"
#include "middleware.h"

class MyTcpServer : public QObject
{
    Q_OBJECT
public:
    enum Mode {SPARRING, CLASSICTUL, NEWTUL_1, NEWTUL_2, NEWTUL_3} mode;
    const int roundTimerDelay = 1000;

    explicit MyTcpServer(QObject *parent = nullptr);
    void setMode(Mode mode);
    Mode getMode();
    short getAdmonition(bool player); // 0 - красный, 1 - синий
    short getWarning(bool player); // 0 - красный, 1 - синий
    int getOverallScore(bool player); // 0 - красный, 1 - синий


// !!!Сигнал вызывает слот, т. е. слот - функция, которая исполняется, а сигнал её вызывает!!!
public slots:
    void slotNewConnection();
    void slotServerRead();
    void slotClientDisconnected();

    void slotAdmonition(bool player); // 0 - красный, 1 - синий
    void slotWarning(bool player); // 0 - красный, 1 - синий
    void slotCancelAdmonition(bool player); // 0 - красный, 1 - синий
    void slotCancelWarning(bool player); // 0 - красный, 1 - синий
    void slotChangeNewTulLevel(short level);
    void slotReset();

    void slotTimerStart();
    void slotTimerPause(short time = 0); // time - время паузы
    void slotTimerStop();

signals:
    void signalScoreUpdate(int judgeNum, int red, int blue); // Сигнал, вызываемый при изменении счёта судьями
    void signalDisqualification(bool player); // Сигнал, вызываемый при дисквалификации одного из игроков. 0 - красный, 1 - синий
    void signalTimeOver(); // Время таймера вышло
    void signalAdmonition(short redAdmonition, short blueAdmonition); // Вызывается при получении Чуя (замечания)
    void signalWarning(short redWarning, short blueWarning); // Вызывается при получении Гамжуна (предупреждения)
    void signalTimerEvent(short timeElapsed); // Вызывается при каждом срабатывании таймера
    void signalJudgeNumError(ulong judgeNum);

protected:
    void timerEvent(QTimerEvent *event);
    QTcpServer * mTcpServer;
    QTcpSocket * mTcpSocket;
    QBasicTimer mainTimer;
    QBasicTimer pauseTimer;
    std::vector <JudgementModes *> Judges; // Нужно для обработки различных режимов при нажатии на кнопки
    short roundTimeElapsed; // Время, прошедшее с начала запуска таймера в секундах
    short pauseTimeElapsed; // Для хранения времени медицинского таймера
    short roundTime; // Время, которое длится один раунд
    short pauseTime; // Время, которое длится пауза
    short redAdmonition = 0, blueAdmonition = 0, redWarning = 0, blueWarning = 0;
};

#endif // MYTCPSERVER_H


Этот класс периодически дорабатывается другим разработчиком. Поэтому появилась идея расширить данный класс (создать обертку) с помощью следующего класса:

extendedmytcpserver.h
#ifndef EXTENDEDMYTCPSERVER_H
#define EXTENDEDMYTCPSERVER_H

#include <QObject>
#include "mytcpserver.h"

/*
    Данный класс расширяет стандартный class MyTcpServer
    Здесь находятся функции и методы, для передачи данных из C++ в QML
*/
class ExtendedMyTcpServer : public MyTcpServer
{

    //Соединяем QML характеристики с серверным API (read/write/notify)
    //Позволяет передавать/получать сигналы с QML кода в C++ структуру
    Q_PROPERTY(short QRoundTimeElapsed  READ QRoundTimeElapsed     NOTIFY timeChanged)
    Q_PROPERTY(short QPauseTimeElapsed  READ QPauseTimeElapsed     NOTIFY timeChanged)
    Q_PROPERTY(short QRoundTime         READ QRoundTime       WRITE setRoundTime         NOTIFY timeChanged)
    Q_PROPERTY(short QPauseTime         READ QPauseTime       WRITE setPauseTime         NOTIFY timeChanged)
    Q_PROPERTY(short QRedAdmonition     READ QRedAdmonition   WRITE setRedAdmonition     NOTIFY admonitionChanged)
    Q_PROPERTY(short QBlueAdmonition    READ QBlueAdmonition  WRITE setBlueAdmonition    NOTIFY admonitionChanged)
    Q_PROPERTY(short QRedWarning        READ QRedWarning      WRITE setRedWarning        NOTIFY warningChanged)
    Q_PROPERTY(short QBlueWarning       READ QBlueWarning     WRITE setBlueWarning       NOTIFY warningChanged)

public:
    explicit ExtendedMyTcpServer(QObject *parent = nullptr); //явное наследование от родителя, обязательно для QML древа

    //геттеры (READ) для Q_PROPERTY.
    short QTimeElapsed()         {return roundTimeElapsed;}
    short QPauseTimeElapsed()    {return pauseTimeElapsed;}
    short QRoundTime()           {return roundTime;}
    short QPauseTime()           {return pauseTime;}
    short QRedAdmonition()       {return redAdmonition;}
    short QBlueAdmonition()      {return blueAdmonition;}
    short QRedWarning()          {return redWarning;}
    short QBlueWarning()         {return blueWarning;}

    /*сеттеры вся суть ->
     * 1. испустить сигнал categoryChanged() с сообщением для логирования.
     * 2. Передать параметр из QML в C++ структуру.
    */

    void setRoundTime(const short& QRoundTime);
    void setPauseTime(const short& QPauseTime);
    void setRedAdmonition(const short& QRedAdmonition);
    void setBlueAdmonition(const short& QBlueAdmonition);
    void setRedWarning(const short& QBlueWarning);
    void setBlueWarning(const short& QBlueWarning);

public slots:


signals:
    //Notify signals
    void timeChanged();
    void admonitionChanged();
    void warningChanged();
};

#endif // EXTENDEDMYTCPSERVER_H


Сейчас этот вариант не работает. QML не может получить доступ к свойствам, как я понял из-за наследования. Если вставляю все свойства в главный файл - все работает хорошо, как и следует. Но мне желательно представить код в виде обертки, так удобнее разрабатывать.

P.S. Проект создан в рамках обучения, поэтому вполне допускаю, что идея плохая. Если есть какое-то другое решение, то буду признателен. Но интерфейс уже написан на QML, не хотелось бы переписывать его на чистом QT.
  • Вопрос задан
  • 128 просмотров
Решения вопроса 1
vt4a2h
@vt4a2h
Senior software engineer (C++/Qt/boost)
Скорее всего, вы просто не зарегистрировали тип с помощью qmlRegisterType. Это нужно сделать для всех классов, которые будут использоваться в QML. Тут есть больше деталей: https://doc.qt.io/qt-5/qtqml-cppintegration-define...

Есть ещё вот такая техника: https://doc.qt.io/qt-5/qtqml-cppintegration-define...
Возможно, это именно то, что вам необходимо.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы