Evgenii Legotckoi
Evgenii LegotckoiЖел. 4, 2015, 12:18 Т.Қ.

Qt/C++ - 027-сабақ. QGraphicsScene ішіндегі геометриялық фигуралар мысалында Qt-тағы полиморфизм

Полиморфизм - OOP (объектіге бағытталған бағдарламалау) парадигмаларының бірі. Полиморфизм базалық класстың іске асырылуы осы сыныптан мұра болатын болашақ сыныптарға белгісіз қасиеттер мен әдістерді қамтамасыз ету мүмкіндігін жүзеге асырады. Яғни, бұл жағдайда базалық сыныпта тапсырмаларды жүзеге асыру үшін барлық қажетті әдістер жиынтығы бар, бірақ белгілі бір әдістерді нақты жүзеге асыру ұрпақ кластарына жүктеледі. Және, әдетте, базалық класс абстрактілі, яғни одан объектілер жасалмайды.

Мысалы, ағымдағы пішінді таңдай отырып, графикалық көрініс тінтуірмен бірнеше геометриялық фигураларды салуға болатын бағдарламаны іске асыру қажет. қолданбадағы түймелерді пайдалану. Мұны істеу үшін сіз бірнеше сыныптарды жасай аласыз, олардың әрқайсысы барлық қажетті функционалдылықты жүзеге асырады және шын мәнінде әр сыныптағы кодтың көп бөлігін қайталайды, бұл дамуды қиындатады және шатастырады. Немесе бір базалық класс жасай аласыз, мысалы, QGraphicsItem ішінен мұраға алынатын Сурет және осында барлық негізгі функционалдылықты жүзеге асыруға болады. класс, содан кейін қазірдің өзінде осы сыныптан мұра болатын үш класс жасаңыз, бірақ оларда тек фигураның өзін салу әдісін жүзеге асырыңыз: Romb, Square, Triangle.

Келесі суретте Figure базалық класы үшін мұрагерлік логика көрсетілген. Figure класының көп мұрасы сигналдар мен слоттармен жұмысты орындау үшін де қолданылды.


Жоба құрылымы - Мысал бойынша полиморфизм

  • PaintFigure.pro - жоба профилі;
  • mainwindow.h - қолданбаның негізгі терезесінің тақырып файлы;
  • mainwindow.cpp - қолданбаның негізгі терезесі үшін бастапқы код файлы;
  • paintscene.h - графикалық көрініс тақырыбының файлы;
  • paintscene.cpp - графикалық көріністің бастапқы код файлы;
  • figure.h - фигуралардың негізгі класының тақырып файлы;
  • figure.cpp - фигуралар класының бастапқы код файлы;
  • romb.h - Rhombus класының тақырып файлы;
  • romb.cpp - Ромб класының бастапқы код файлы;
  • square.h - Square/Rectangle класының тақырып файлы;
  • square.cpp - Шаршы/Тіктөртбұрыш класының бастапқы код файлы;
  • triangle.h - Triangle класының тақырып файлы;
  • triangle.cpp - үшбұрыш сыныбының бастапқы код файлы;
  • mainwindow.ui - қолданбаның негізгі терезесінің пішіні.

mainwindow.ui - PaintFigure.pro - main.cpp

Негізгі қолданба терезесінің келесі пішінін конструкторда сызыңыз. Ал PaintFigure.pro және main.cpp файлдары әдепкі бойынша жасалған болып қалады және өзгертілмейді.

mainwindow.h

Қолданбаның негізгі терезесінің тақырып файлында геометриялық фигураларды салуға жауапты болатын теңшелген PaintScene графикалық көрінісін жариялау керек. Біз сондай-ақ resizeEvent() әдісін қайта анықтаймыз, онда қолданба терезесінің өлшеміне байланысты графикалық көріністің өлшемін қайта есептейміз. Бұл таза косметикалық.

#ifndef MAINWINDOW\_H
#define MAINWINDOW\_H

#include <QMainWindow>
#include <QTimer>
#include <QResizeEvent>

#include "paintscene.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q\_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    PaintScene *scene;  // Объявляем кастомную графическую сцену
    QTimer *timer;      /* Определяем таймер для подготовки актуальных размеров
                         * графической сцены
                         * */
private:
    /* Переопределяем событие изменения размера окна
     * для пересчёта размеров графической сцены
     * */
    void resizeEvent(QResizeEvent * event);

private slots:
    // Таймер для изменения размеров сцены при изменении размеров Окна приложения
    void slotTimer();
    void on\_pushButton\_clicked();       // Включаем отрисовку Ромба
    void on\_pushButton\_2\_clicked();     // Включаем отрисовку Квадрата
    void on\_pushButton\_3\_clicked();     // Включаем отрисовку Треугольника
};

#endif // MAINWINDOW\_H

mainwindow.cpp

Қолданбаның негізгі терезесінде үш түйме бар, оны басу арқылы тінтуірдің көмегімен сурет салуға қажетті фигураның түрін орнатамыз. Сондай-ақ қайта сызу таймерінен сигнал бойынша терезе өлшемін өзгертуге арналған слот бар.

#include "mainwindow.h"
#include "ui\_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    scene = new PaintScene();   // Инициализируем графическую сцену
    ui->graphicsView->setScene(scene);
    ui->graphicsView->setRenderHint(QPainter::Antialiasing);                // Устанавливаем сглаживание
    ui->graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);   // Отключаем скроллбар по вертикали
    ui->graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Отключаем скроллбар по горизонтали

    timer = new QTimer();       // Инициализируем таймер
    connect(timer, &QTimer::timeout, this, &MainWindow::slotTimer);
    timer->start(100);          // Запускаем таймер
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::slotTimer()
{
    /* Переопределяем размеры графической сцены в зависимости
     * от размеров окна
     * */
    timer->stop();
    scene->setSceneRect(0,0, ui->graphicsView->width() - 20, ui->graphicsView->height() - 20);
}

void MainWindow::resizeEvent(QResizeEvent *event)
{
    timer->start(100);
    QMainWindow::resizeEvent(event);
}

// Ромб
void MainWindow::on\_pushButton\_clicked()
{
    scene->setTypeFigure(PaintScene::RombType);
}

// Квадрат
void MainWindow::on\_pushButton\_2\_clicked()
{
    scene->setTypeFigure(PaintScene::SquareType);
}

// Треугольник
void MainWindow::on\_pushButton\_3\_clicked()
{
    scene->setTypeFigure(PaintScene::TriangleType);
}

paintscene.h

Теңшелетін графикалық көріністің тақырып файлы. Бұл көріністе кескіннің ағымдағы түрін көрсету үшін сақтауға жауап беретін Q_PROPERTY қасиеті бар. Түрлер тізімі enum FigureTypes арқылы көрсетіледі. Сондай-ақ Figure класының данасы болып табылатын tempFigure нысанының мәлімдемесі бар. Бұл класс полиморфизм парадигмасына сәйкес базалық класс болып табылады, сондықтан ол графикалық сахнада сызылған фигураны уақытша сақтау үшін қолданылады, өйткені тінтуірдің көмегімен фигураның өлшемін орнатудың барлық негізгі әдістері базада жүзеге асырылады. сынып Сурет.

Тінтуір оқиғасының әдістері де қайта анықталған. mousePressEvent әдісінде сурет салу үшін геометриялық фигура құрылады, ал mouseMoveEvent әдісінде тінтуірдің батырмасы босатылғанша тінтуір курсорының орнына байланысты пішін қайта сызылады.

#ifndef PAINTSCENE\_H
#define PAINTSCENE\_H

#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include "figure.h"

class PaintScene : public QGraphicsScene
{
    Q\_OBJECT
    // Свойство текущего типа используемой фигуры
    Q\_PROPERTY(int typeFigure
               READ typeFigure WRITE setTypeFigure
               NOTIFY typeFigureChanged)

public:
    explicit PaintScene(QObject *parent = 0);
    ~PaintScene();

    int typeFigure() const;                 // Возвращение текущего типа
    void setTypeFigure(const int type);     // Установка текущего типа

    // Перечисление типов используемых фигур
    enum FigureTypes {
        SquareType,
        RombType,
        TriangleType
    };

signals:
    void typeFigureChanged();               // Сигнал об изменении типа текущей фигуры

private:
    /* Объект для временного хранения рисуемой фигуры
     * Является объектом базового класса для всех трёх типов фигур в примере
     * */
    Figure *tempFigure;
    int m\_typeFigure;   // текущий тип фигуры

private:
    // Для рисования используем события мыши
    void mousePressEvent(QGraphicsSceneMouseEvent * event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);

};

#endif // PAINTSCENE\_H

paintscene.cpp

#include "paintscene.h"
#include "romb.h"
#include "triangle.h"
#include "square.h"

PaintScene::PaintScene(QObject *parent) : QGraphicsScene(parent)
{

}

PaintScene::~PaintScene()
{

}

int PaintScene::typeFigure() const
{
    return m\_typeFigure;
}

void PaintScene::setTypeFigure(const int type)
{
    m\_typeFigure = type;
}

void PaintScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    /* Устанавливаем конечную координату положения мыши
     * в текущую отрисовываемую фигуру
     * */
    tempFigure->setEndPoint(event->scenePos());
    /* Обновляем содержимое сцены,
     * необходимо для устранения артефактов при отрисовке фигур
     * */
    this->update(QRectF(0,0,this->width(), this->height()));
}

/* Как только нажали кнопку мыши, создаём фигуру одного из трёх типов
 * и помещаем её на сцену, сохранив указатель на неё в переменной
 * tempFigure
 * */
void PaintScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    switch (m\_typeFigure) {
    case SquareType: {
        Square *item = new Square(event->scenePos());
        item->setPos(event->pos());
        tempFigure = item;
        break;
    }
    case RombType: {
        Romb *item = new Romb(event->scenePos());
        item->setPos(event->pos());
        tempFigure = item;
        break;
    }
    case TriangleType: {
        Triangle *item = new Triangle(event->scenePos());
        item->setPos(event->pos());
        tempFigure = item;
        break;
    }
    default:{
        Square *item = new Square(event->scenePos());
        item->setPos(event->pos());
        tempFigure = item;
        break;
    }
    }
    this->addItem(tempFigure);
}

сурет.сағ

Геометриялық фигураларды жасауға арналған негізгі класстың тақырып файлы. Ол полиморфизмді қамтамасыз ететін қай фигура сызылатынына қарамастан геометриялық фигураны салу шекараларын анықтаудың негізгі функционалдығын қамтамасыз етеді. Көрсету үшін екі нүкте пайдаланылады: бастау және соңы . Сызу бастапқы нүктеден басталады және ол өз орнын өзгертпейді, бірақ соңғы нүкте фигура салынған тікбұрышты аймақтың қарама-қарсы бұрышының координатасы болып табылады. Осы нүктелерге байланысты фигуралардың барлық басқа негізгі нүктелері және сәйкесінше осы фигуралардың шекаралары қайта сызылады.

#ifndef FIGURE\_H
#define FIGURE\_H

#include <QObject>
#include <QGraphicsItem>
#include <QDebug>

class Figure : public QObject, public QGraphicsItem
{
    Q\_OBJECT
    // Свойство стартовой точки, относительно которой отрисовываем фигуру
    Q\_PROPERTY(QPointF startPoint
               READ startPoint WRITE setStartPoint
               NOTIFY pointChanged)
    // Свойство конечной точки, до куда отрисовываем фигуру
    Q\_PROPERTY(QPointF endPoint
               READ endPoint WRITE setEndPoint
               NOTIFY pointChanged)
public:
    explicit Figure(QPointF point, QObject *parent = 0);
    ~Figure();

    QPointF startPoint() const; // Стартовая точка
    QPointF endPoint() const;   // Конечная точка

    void setStartPoint(const QPointF point);    // Установка стартовой точки
    void setEndPoint(const QPointF point);      // Установка конечной точки

signals:
    void pointChanged();    // Сигнал об изменении точки

private:
    QPointF m\_startPoint;   // Стартовая точка
    QPointF m\_endPoint;     // Конечная точка

    QRectF boundingRect() const;    // Область, в которой содержится фигура

public slots:
    void updateRomb();     // Слот обновления области, в которой содержится фигура
};

#endif // FIGURE\_H

цифр.cpp

#include "figure.h"
#include <QPainter>

Figure::Figure(QPointF point, QObject *parent) :
    QObject(parent), QGraphicsItem()
{
    // Устанавливаем стартовую координату для отрисовки фигуры
    this->setStartPoint(mapFromScene(point));
    this->setEndPoint(mapFromScene(point));
    /* Подключаем сигнал изменения координат к слоту запуска обновления содержимого объекта
     * Сигнал и слот присутствуют в базовом классе
     * */
    connect(this, &Figure::pointChanged, this, &Figure::updateRomb);
}

Figure::~Figure()
{

}

QRectF Figure::boundingRect() const
{
    /* Возвращаем область, в которой лежит фигура.
     * Обновляемая область зависит от стартовой точки отрисовки и от конечной точки
     * */
    return QRectF((endPoint().x() > startPoint().x() ? startPoint().x() : endPoint().x()) - 5,
                  (endPoint().y() > startPoint().y() ? startPoint().y() : endPoint().y()) - 5,
                  qAbs(endPoint().x() - startPoint().x()) + 10,
                  qAbs(endPoint().y() - startPoint().y()) + 10);
}

void Figure::updateRomb()
{
    // Вызываем обновление области, в которой лежит фигура
    this->update((endPoint().x() > startPoint().x() ? startPoint().x() : endPoint().x()) - 5,
                 (endPoint().y() > startPoint().y() ? startPoint().y() : endPoint().y()) - 5,
                 qAbs(endPoint().x() - startPoint().x()) + 10,
                 qAbs(endPoint().y() - startPoint().y()) + 10);
}

void Figure::setStartPoint(const QPointF point)
{
    m\_startPoint = mapFromScene(point);
    emit pointChanged();
}

void Figure::setEndPoint(const QPointF point)
{
    m\_endPoint = mapFromScene(point);
    emit pointChanged();
}

QPointF Figure::startPoint() const
{
    return m\_startPoint;
}

QPointF Figure::endPoint() const
{
    return m\_endPoint;
}

romb.h

Бізге қажет фигура сыныбының тақырып файлында Figure базалық класынан мұра алу және -дан мұраланған paint(), әдісін қайта анықтау қажет. Сурет, класс атасы, яғни QGraphicsItem. Бұл әдіс осы геометриялық фигураны салу логикасын жүзеге асырады.

#ifndef ROMB\_H
#define ROMB\_H

#include <QObject>
#include <QGraphicsItem>
#include "figure.h"

/* Наследуемся от класса Figure,
 * в котором реализован общий для всех фигур функционал
 * */
class Romb : public Figure
{
    Q\_OBJECT

public:
    explicit Romb(QPointF point, QObject *parent = 0);
    ~Romb();

private:
    // Для Ромба реализуем только саму отрисовку
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
};

#endif // ROMB\_H

rhombus.cpp

#include "romb.h"
#include <QPainter>

Romb::Romb(QPointF point, QObject *parent) :
    Figure(point,parent)
{
    Q\_UNUSED(point)
}

Romb::~Romb()
{

}

// Реализуем метод отрисовки
void Romb::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->setPen(QPen(Qt::black, 2));

    QPolygonF polygon;

    polygon << QPointF(startPoint().x() + (endPoint().x() > startPoint().x() ? + 1 : - 1)*
                           abs((endPoint().x() - startPoint().x())/2), startPoint().y())
                << QPointF(endPoint().x(), startPoint().y() + (endPoint().y() > startPoint().y() ? + 1 : - 1)*
                           abs((endPoint().y() - startPoint().y())/2))
                << QPointF(startPoint().x() + (endPoint().x() > startPoint().x() ? + 1 : - 1)*
                           abs((endPoint().x() - startPoint().x())/2), endPoint().y())
                << QPointF(startPoint().x(), startPoint().y() + (endPoint().y() > startPoint().y() ? + 1 : - 1)*
                           abs((endPoint().y() - startPoint().y())/2));

    painter->drawPolygon(polygon);

    Q\_UNUSED(option)
    Q\_UNUSED(widget)
}

Үшбұрыш және Шаршы сыныптары

Класс деректерінің файлдарының құрылымы Romb класына ұқсас, айырмашылығы тек фигуралық сызбаны жүзеге асыру логикасында.

Барлығы

Полиморфизм парадигмасын шебер қолдану нәтижесінде бағдарлама кодының көлемін айтарлықтай азайтуға, сонымен қатар оны қайта пайдалану жиілігін арттыруға болады, әсіресе егер сіз геометриялық сияқты көптеген ұқсас объектілердің болуын білдірсеңіз. пішіндер.

Алынған қосымшаның демонстрациясы бейне оқулықта берілген.

Жобаны zip-архивте жүктеп алу сілтемесі: PaintFigure

Бейне оқулық

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

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

L
  • Ақп. 20, 2018, 5:10 Т.Қ.

Здравствуйте!
В программировании новичок и есть пара вопросов. Буду очень благодарен за ответ.

Не совсем понимаю как:
1) реализовать подобным образом рисование эллипса(конкретно выбор точек по типу как 22-29 строка в romb.cpp);
2) выбор цвета фигур через диалоговое окно выбора цвета (присваиваю переменной Color цвет, после его выбора в QColorDialog и вместо Qt::black пишу Color, но цвет остается черным).


Evgenii Legotckoi
  • Ақп. 21, 2018, 3:37 Т.Ж.

Добрый день!


1) Эллипс можно реализовать так
void Ellipse::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->setPen(QPen(Qt::black, 2));


    QRectF rect(endPoint().x() > startPoint().x() ? startPoint().x() : endPoint().x(),
                endPoint().y() > startPoint().y() ? startPoint().y() : endPoint().y(),
                qAbs(endPoint().x() - startPoint().x()),
                qAbs(endPoint().y() - startPoint().y()));

    painter->drawEllipse(rect);

    Q_UNUSED(option)
    Q_UNUSED(widget)
}
2) Это уже надо смотреть тот участок кода, который вы используете для установки цвета. Возможно там мелкая ошибка. Задайте пожалуйста этот вопрос на форуме и приведите там тот код, который Вы написали.

L
  • Ақп. 21, 2018, 3:53 Т.Ж.

Огромное спасибо!

ЕЕ
  • Там. 20, 2018, 1:02 Т.Қ.

Добрый день, начал только изучать Qt C++.

Никак не могу понять, как удалять последний созданный элемент.
Заранее спасибо.
Evgenii Legotckoi
  • Там. 23, 2018, 5:56 Т.Ж.

Здесь скорее нужно использовать стек из указателей, чтобы хранить поочерёдно добавляемые элементы. Например, QVector в конец которого будете добавлять элементы, которые были добавлены на графическую сцену.

Если вам нужно удалить последний добавленный элемент, то берёте с конца вектора элемент, удаляете его из графической сцены, из вектора и вообще удаляете.

К
  • Мамыр 22, 2022, 6:32 Т.Ж.

Крутой урок! Но как только захотел добавить функцию выделение объекта ( подразумевается перемещение и изменение размера) ничего не получается . Читал что нужно включить флаги ItemIsSelected и ItemIsMovable , и сделал точно также ка к в вашем примере при перетаскивании мышью(23 урок) , но ничего не заработало.Не подскажите как это должно выглядить?

Evgenii Legotckoi
  • Мамыр 23, 2022, 7:23 Т.Ж.

Ну не видя вашего кода, сказать, где у вас ошибка невозможно.
А что касается перетаскивания и разных манипуляций, то можете распотрошить код векторного редактора из этой статьи Qt/C++ - Урок 072. Пример векторного редактора на Qt .
Там достаточно примеров кода по интересующим вас вопросам.
А писать какие-то ещё примеры на эту тему у меня сейчас очень сильно нет времени.

f
  • Жел. 9, 2022, 7:46 Т.Қ.

Здравствуйте! Очень нужна помощь, как сделать так чтобы выбранный пользователем цвет границ фигуры применялся только к новой фигуре(которую только собираешься нарисовать), а не ко всем фигурам(уже нарисованным)? Пожалуйста помогите, никак не могу наладить

Evgenii Legotckoi
  • Жел. 12, 2022, 3:45 Т.Ж.

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

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
Г

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:66ұпай,
  • Бағалау ұпайлары-1
t

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:33ұпай,
  • Бағалау ұпайлары-10
t

Qt - Тест 001. Сигналы и слоты

  • Нәтиже:52ұпай,
  • Бағалау ұпайлары-4
Соңғы пікірлер
G
GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssrАқп. 8, 2024, 6:43 Т.Қ.
Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
F
FynjyШілде 22, 2024, 4:15 Т.Ж.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
BlinCT
BlinCTМаусым 25, 2024, 1 Т.Ж.
Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
BlinCT
BlinCTМамыр 5, 2024, 5:46 Т.Ж.
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

Бізді әлеуметтік желілерде бақылаңыз