P
P
PythonBeginner202019-09-15 16:36:26
Qt
PythonBeginner20, 2019-09-15 16:36:26

How to create a class that extends a C++ library under QT to work in QML?

Hello, the question sounds crazy, but I don’t know how to describe it more competently.
I have file 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

This class is periodically updated by another developer. Therefore, the idea came up to extend this class (create a wrapper) using the following class:
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

Now this option does not work. QML cannot access properties, as I understand it, due to inheritance. If I insert all the properties into the main file, everything works well, as it should. But it is desirable for me to present the code in the form of a wrapper, so it is more convenient to develop.
PS The project was created as part of the training, so I fully admit that the idea is bad. If there is any other solution, I will be grateful. But the interface is already written in QML, I would not want to rewrite it in pure QT.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vitaly, 2019-09-16
@PythonBeginner20

Most likely you just didn't register the type with qmlRegisterType. This must be done for all classes that will be used in QML. There are more details here: https://doc.qt.io/qt-5/qtqml-cppintegration-define...
There is also this technique: https://doc.qt.io/qt-5/qtqml-cppintegration -define...
Perhaps this is exactly what you need.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question