Evgenii Legotckoi
Evgenii Legotckoi20 вересня 2015 р. 12:08

Як зробити гру за допомогою Qt - Урок 3. Взаємодія з іншими об'єктами

Після того, як у грі є анімована Муха , яка пересувається під впливом клавіш клавіатури, настав час додати сенс у гру. Додамо мету Мусі , наприклад, вона поїдатиме яблука, які будуть підраховуватися. Тобто необхідно налаштувати взаємодію Мухи з іншими об'єктами, у разі з яблуками.

Для яблук необхідно створити окремий клас, який також буде успадкований від QGraphicsItem. При створенні яблука повинні мати випадковий колір, що також ініціалізуватиметься в конструкторі класу яблук за допомогою функції qrand() .

Коли Муха натикається на яблуко, необхідно передавати цю інформацію в ядро гри, яке знаходиться в класі widget. Для цього будемо під час руху Мухи аналізувати об'єкти, які потрапляють у поле її зору, та з якими необхідно відпрацювати взаємодію.

    /* Производим проверку на то, наткнулась ли муха на какой-нибудь
     * элемент на графической сцене.
     * Для этого определяем небольшую область перед мухой,
     * в которой будем искать элементы
     * */
    QList<QGraphicsItem *> foundItems = scene()->items(QPolygonF()
                                                           << mapToScene(0, 0)
                                                           << mapToScene(-20, -20)
                                                           << mapToScene(20, -20));
    /* После чего проверяем все элементы.
     * Один из них будет сама Муха - с ней ничего не делаем.
     * А с остальными высылаем сигнал в ядро игры
     * */
    foreach (QGraphicsItem *item, foundItems) {
        if (item == this)
            continue;
        emit signalCheckItem(item);
    }

Як тільки Муха виявила об'єкт, відмінний від неї самої, передаємо його в ядро гри, де гра перевірить, що об'єкт є яблуком і видалить його, збільшивши рахунок гри на одиницю.

void Widget::slotDeleteApple(QGraphicsItem *item)
{
    /* Получив сигнал от Мухи
     * Перебираем весь список яблок и удаляем найденное яблоко
     * */
    foreach (QGraphicsItem *apple, apples) {
        if(apple == item){
            scene->removeItem(apple);   // Удаляем со сцены
            apples.removeOne(item);     // Удаляем из списка
            delete apple;               // Вообще удаляем
            ui->lcdNumber->display(count++);    /* Увеличиваем счёт на единицу
                                                 * и отображаем на дисплее
                                                 * */
        }
    }
}

Створення ж яблук, із якими відбуватиметься взаємодія має здійснюватися з певною періодичністю, що ініціалізуватиметься спеціальним таймером.

    /* Раз в секунду отсылаем сигнал на создание яблока в игре
     * */
    timerCreateApple = new QTimer();
    connect(timerCreateApple, &QTimer::timeout, this, &Widget::slotCreateApple);
    timerCreateApple->start(1000);

    /* Подключаем сигнал от Мухи, в котором передаются Объекты, на которые
     * наткнулась Муха
     * */
    connect(triangle, &Triangle::signalCheckItem, this, &Widget::slotDeleteApple);

Створення яблука виконується у функції slotCreateApple()

void Widget::slotCreateApple()
{
    Apple *apple = new Apple(); // Создаём яблоко
    scene->addItem(apple);      // Помещаем его в сцену со случайной позицией
    apple->setPos((qrand() % (251)) * ((qrand()%2 == 1)?1:-1),
                  (qrand() % (251)) * ((qrand()%2 == 1)?1:-1));
    apple->setZValue(-1);       /* Помещаем яблоко ниже Мухи, то есть Муха
                                 * на сцене будет выше яблок
                                 * */
    apples.append(apple);       // Добавляем Яблоко в Список
}

Програмний код уроку

У цьому уроці вносяться зміни до програмного коду попередніх уроків.

Після того, як описаний процес взаємодії, наводжу повний програмний код класу, який відповідає за створення яблук.

apple.h

У цьому файлі додана лише змінна, яка відповідатиме за

#ifndef APPLE_H
#define APPLE_H

#include <QObject>
#include <QGraphicsItem>
#include <QGraphicsScene>
#include <QPainter>

class Apple : public QObject, public QGraphicsItem
{
    Q_OBJECT
public:
    explicit Apple(QObject *parent = 0);
    ~Apple();

signals:

public slots:

protected:
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

private:
    int color;
};

#endif // APPLE_H

apple.cpp

#include "apple.h"

Apple::Apple(QObject *parent)
    : QObject(parent), QGraphicsItem()
{
    /* Устанавливаем улчай номер цвета яблока
     * */
    color = qrand() % ((3 + 1) - 1) + 1;
}

Apple::~Apple()
{

}

QRectF Apple::boundingRect() const
{
    return QRectF(-20,-20,40,40);   // Ограничиваем область, в которой лежит яблоко
}

void Apple::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    // Тушка яблока
    QPainterPath path(QPointF(0,-10));
    path.cubicTo(0,-10, -5,-14,  -12,-8);
    path.cubicTo(-12,-8, -20,12, -10,15);
    path.cubicTo(-10,15, -5,20, 0,16);
    path.cubicTo(0,16, 5,20, 10,15);
    path.cubicTo(10,15, 20,12, 12,-8);
    path.cubicTo(12,-8, 5,-14,  0,-10);

    /* Выбираем цвет яблока по случайно сгенерированному номеру
     * */
    switch (color)
    {
    case 1:
        painter->setBrush(Qt::red);
        break;
    case 2:
        painter->setBrush(Qt::green);
        break;
    case 3:
        painter->setBrush(Qt::yellow);
        break;
    }
    painter->drawPath(path);

    // Хвостик яблока
    painter->setPen(QPen(Qt::black, 2));
    QPainterPath path2(QPointF(0,-10));
    path2.cubicTo(0,-10,4,-18,10,-20);
    painter->setBrush(Qt::NoBrush);
    painter->drawPath(path2);

    //Листик яблока
    painter->setPen(QPen(Qt::black, 1));
    QPainterPath path3(QPointF(0,-10));
    path3.cubicTo(0,-10,-2,-20,-15,-20);
    path3.cubicTo(-15,-20,-14,-12,0,-10);
    painter->setBrush(Qt::green);
    painter->drawPath(path3);

    Q_UNUSED(option);
    Q_UNUSED(widget);
}

трикутник.h

Також необхідно додати сигнал до заголовкового файлу Мухи , який передаватиме в ядро гри об'єкти, на які натрапила Муха.

signals:
    /* Сигнал, который передаётся в ядро игры с элементом QGraphicsItem,
     * на который наткнулась муха, и требуется принять решение о том,
     * что с этим элементом делать.
     * */
    void signalCheckItem(QGraphicsItem *item);

triangle.cpp

У цьому класі зміни вносяться лише у функцію-слот, що відповідає обробку сигналу від ігрового таймера.

void Triangle::slotGameTimer()
{
    /* Проверяем, нажата ли была какая-либо из кнопок управления объектом.
     * Прежде чем считать шажки
     * */
    /* Программный код из прошлого урока */

    /* Производим проверку на то, наткнулась ли муха на какой-нибудь
     * элемент на графической сцене.
     * Для этого определяем небольшую область перед мухой,
     * в которой будем искать элементы
     * */
    QList<QGraphicsItem *> foundItems = scene()->items(QPolygonF()
                                                           << mapToScene(0, 0)
                                                           << mapToScene(-20, -20)
                                                           << mapToScene(20, -20));
    /* После чего проверяем все элементы.
     * Один из них будет сама Муха - с ней ничего не делаем.
     * А с остальными высылаем сигнал в ядро игры
     * */
    foreach (QGraphicsItem *item, foundItems) {
        if (item == this)
            continue;
        emit signalCheckItem(item);
    }

    /* Проверка выхода за границы поля
     * Если объект выходит за заданные границы, то возвращаем его назад
     * */
    /* Программный код из прошлого урока */
}

віджет.h

Ядро гри розвивається та ускладнюється. На цей раз необхідно додати таймер для періодичного створення яблук у грі, Список, в якому зберігатимуться всі яблука та лічильник очок. А також необхідно додати слоти для створення та видалення яблук.

private:
    QTimer          *timerCreateApple;  // Таймер для периодического создания яблок в игре

    QList<QGraphicsItem *> apples;  // Список со всеми яблоками, присутствующими в игре
    double count;   // Переменная, которая хранит счёт игре

private slots:
    // Слот для удаления яблок если Муха наткнулая на это яблоко
    void slotDeleteApple(QGraphicsItem * item);
    void slotCreateApple();     // Слот для создания яблок, срабатывает по таймеру

widget.cpp

Реалізуємо функції-слоти, а також налаштовуємо коннект для роботи з об'єктами в грі.

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->resize(600,640);          /// Задаем размеры виджета, то есть окна
    this->setFixedSize(600,640);    /// Фиксируем размеры виджета

    count = 0;

    scene = new QGraphicsScene();   /// Инициализируем графическую сцену
    triangle = new Triangle();      /// Инициализируем треугольник

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

    scene->setSceneRect(-250,-250,500,500); /// Устанавливаем область графической сцены

    scene->addItem(triangle);   /// Добавляем на сцену треугольник
    triangle->setPos(0,0);      /// Устанавливаем треугольник в центр сцены



    /* Инициализируем таймер и вызываем слот обработки сигнала таймера
     * у Треугольника 100 раз в секунду.
     * Управляя скоростью отсчётов, соответственно управляем скоростью
     * изменения состояния графической сцены
     * */
    timer = new QTimer();
    connect(timer, &QTimer::timeout, triangle, &Triangle::slotGameTimer);
    timer->start(1000 / 100);

    /* Раз в секунду отсылаем сигнал на создание яблока в игре
     * */
    timerCreateApple = new QTimer();
    connect(timerCreateApple, &QTimer::timeout, this, &Widget::slotCreateApple);
    timerCreateApple->start(1000);

    /* Подключаем сигнал от Мухи, в котором передаются Объекты, на которые
     * наткнулась Муха
     * */
    connect(triangle, &Triangle::signalCheckItem, this, &Widget::slotDeleteApple);

}

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

void Widget::slotDeleteApple(QGraphicsItem *item)
{
    /* Получив сигнал от Мухи
     * Перебираем весь список яблок и удаляем найденное яблоко
     * */
    foreach (QGraphicsItem *apple, apples) {
        if(apple == item){
            scene->removeItem(apple);   // Удаляем со сцены
            apples.removeOne(item);     // Удаляем из списка
            delete apple;               // Вообще удаляем
            ui->lcdNumber->display(count++);    /* Увеличиваем счёт на единицу
                                                 * и отображаем на дисплее
                                                 * */
        }
    }
}

void Widget::slotCreateApple()
{
    Apple *apple = new Apple(); // Создаём яблоко
    scene->addItem(apple);      // Помещаем его в сцену со случайной позицией
    apple->setPos((qrand() % (251)) * ((qrand()%2 == 1)?1:-1),
                  (qrand() % (251)) * ((qrand()%2 == 1)?1:-1));
    apple->setZValue(-1);       /* Помещаем яблоко ниже Мухи, то есть Муха
                                 * на сцене будет выше яблок
                                 * */
    apples.append(apple);       // Добавляем Яблоко в Список
}

Підсумок

В результаті у Вас на графічній сцені будуть випадково виникати яблука, які поїдатиме Муха , а також кількість з'їдених яблук враховуватиметься в лічильнику.

Також у відеоуроці за цією статтею дано додаткові коментарі та продемонстровано роботу гри.

Повний список статей цього циклу:

Відеоурок

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

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

ЛП
  • 19 березня 2017 р. 17:44

Классно пишешь! Мне прям нравится правильная подача "логики" ООП! Легкая корректировка: apples.append(apple); // Добавляем яблоко в Список И вопрос: foreach (QGraphicsItem *item, foundItems) { if (item == this) continue; emit signalCheckItem(item); } где формируется указатель item?

Evgenii Legotckoi
  • 20 березня 2017 р. 00:03

В данном случае он формируется в следующем участке кода:

void Widget::slotCreateApple()
{
    Apple *apple = new Apple(); // Создаём яблоко
    scene->addItem(apple);      // Помещаем его в сцену со случайной позицией
   
    ***
}

Класс Apple является наследником QGraphicsItem

ЛП
  • 20 березня 2017 р. 01:42

И еще пару вопросов! =) Почему именно в .h файле устанавливается указатель на родителя предка? Почему ты использовал ключевое слово explicit?

explicit Apple(QObject *parent = 0);
Почему указатель на предка передается в QObject? Почему мы обделили QGraphicsItem?
Apple::Apple(QObject *parent) : QObject(parent), QGraphicsItem()
Evgenii Legotckoi
  • 20 березня 2017 р. 02:21

excplicit - убирает возможность неявного преобразования. Неявные преобразования вообще могут бед наделать, лучше отключать такую возможность для конструкторов сложных классов.

Установка указателя на предка в конструкторе - это стандартная практика для Qt фреймворка. Указатель на parent присутствует в конструкторах всех классов, которые наследованы от базового класса QObject.

QGraphicsItem - является одним из тех немногих классов, которые не наследованы от QObject. Поэтому приходится применять множественное наследование, чтобы использовать систему сигналов и слотов, которая работает только с теми классами, которые были наследованы от QObject. Соответственно parent передаётся в базовый класс QObject.

ЛП
  • 20 березня 2017 р. 04:36
excplicit - убирает возможность неявного преобразования. Неявные преобразования вообще могут бед наделать, лучше отключать такую возможность для конструкторов сложных классов.

https://www.slideshare.net/IgorShkulipa/c-stl-qt-03 исходя из 6 слайда: "Инструментарий спроктирован так, что для QObject и всех его потомков конструктор копирования и оператор присваивания недоступны- они объявлены в раделе private через макрос Q_DISABLE_COPY;

MyClass ob1(1); 
MyClass ob2 = 10;  // Не прокатит! 

Только вот зачем оно нужно? (или не заморачиваться и все время писать explicit?)

Evgenii Legotckoi
  • 20 березня 2017 р. 04:50

Если делать неявное преобразование, как вы его показали, то да, работать не будет:

MyClass ob1(1); 
MyClass ob2 = 10; // Здесь ошибка

А вот если использовать новомодный синтаксис из более свежих стандартов:

MyClass ob1(1); 
MyClass ob2 = {10}; // Это будет работать

И Q_DISABLE_COPY здесь не спасает на данный момент, он условно только "отключает копирование". А excplicit выключит вариант неявного преобразования с новым синтаксисом.

ЛП
  • 20 березня 2017 р. 04:53

А вот в чем смысл этих всех запретов?

Evgenii Legotckoi
  • 20 березня 2017 р. 05:01

На мой взгляд, неявные преобразования могут носить достаточно непредсказуемый характер в зависимости от компиляторов.

На Qt/С++ я конечно давно не сталкивался с проблемами неявных преобразований, видимо сказывается наличие практики этих самых запретов и ограничений. Но когда занимался разработкой на Си/С++ под AVR и STM32, то там эти преобразования крови много попортили.

Вообще, в чём смысл всех запретов? - Контроль и единообразие, чтобы снизить хаос в проекте.

ЛП
  • 20 березня 2017 р. 05:55

Я все-таки не понимаю с item! В этой функции то понятно- item передается как аргумент.

void Widget::slotDeleteApple(QGraphicsItem *item) { /* Получив сигнал от Мухи * Перебираем весь список яблок и удаляем найденное яблоко * */ foreach (QGraphicsItem *apple, apples) { if(apple == item){ scene->removeItem(apple); // Удаляем со сцены apples.removeOne(item); // Удаляем из списка delete apple; // Вообще удаляем ui->lcdNumber->display(count++); /* Увеличиваем счёт на единицу * и отображаем на дисплее * */ } } }
А вот тут:
void Triangle::slotGameTimer(){ .... foreach (QGraphicsItem *item, foundItems) { if (item == this) continue; emit signalCheckItem(item); } ... }
Как foreach понимает какой из указателей QGraphicsItem он сейчас будет перебирать?

Вопрос снят.

Evgenii Legotckoi
  • 20 березня 2017 р. 06:08

foreach перебирает все указатели, которые находятся в контейнере foundItems

// На графической сцене забираем все контейнеры в определённой области, заданной с помощью QPolygonF
QList<QGraphicsItem *> foundItems = scene()->items(QPolygonF()
                                                           << mapToScene(0, 0)
                                                           << mapToScene(-20, -20)
                                                           << mapToScene(20, -20));

foreach абсолютно всё равно, какие в контейнере классы, главное, чтобы у них один общий базовый класс, в данном случае - это QGraphicsItem . То есть: QGraphicsItem можно скастовать в Apple или в Triangle , поскольку они наследованы от QGraphicsItem, просто если класс изначально задавался как Apple, его не получится скастовать из QGraphicsItem в Trianle. Это возможно, благодаря парадигме полиморфизма

А сам по себе foreach можете перебирать все объекты в контейнере QList, поскольку данный контейнер имеет итератор. Не было бы итератора, то и не смог бы перебирать.

P/S/ для вставки программного кода в комментарий используйте, пожалуйста, специальный диалог для вставки кода. Он вызывается кнопочкой с иконкой "{}" на тулбаре редактора комментариев. Также рядом есть кнопочка предварительного просмотра комментария.

ЛП
  • 20 березня 2017 р. 11:29

И еще вопрос: А когда именно вызывается метод paint? Ну понятно что по идее- при столкновении, по таймеру при перерисовке. Я то сначала думал, что он вызывается после метода setRotation() или setPos(). Стал смотреть в отладчике, а нифига!

Evgenii Legotckoi
  • 20 березня 2017 р. 11:43

Метод update() вызывает принудительную перерисовку, также вызывается по некоторым методам, таким как setX(), setY() во внутренностях Qt. Некоторые методы, наподобие paint, вызываются в порядке внутренней очереди. Здесь уже нужно смотреть исходники Qt.

v
  • 04 травня 2017 р. 10:21

у меня такая проблема .делал все как на видео все понятно .но выдает ошибку ошибка: 'Apple' was not declared in this scope ошибка: 'apple' was not declared in this scope ошибка: expected type-specifier before 'Apple' : ошибка: expected ';' before 'Apple' ругается на одну строчку 4 раза вот эта строчка Apple *apple = new Apple(); // Создаём яблоко

v
  • 04 травня 2017 р. 10:28

http://imglink.ru/show-image.php?id=709c66221545c26eec66d6586f2b7ff1 вот скриншот

ЛП
  • 04 травня 2017 р. 10:52

Когда у меня подобного рода "лабуда" я делаю следующией действия: 1. пересобираю проект 2. Удаляю папку debug и релиз, все make и qmake файлы 3. Перезапускаю qt Таких вот "чудес" раз по 5 на день. + теневую сборку отключаю

Evgenii Legotckoi
  • 04 травня 2017 р. 10:52

Скорее всего заголовочный файл не подключён в файле widget.cpp.

#include "apple.h"
v
  • 04 травня 2017 р. 11:10

Спасибо .чет не заметил что не подключил

L
  • 24 травня 2017 р. 04:24

При столкновении объектов отсылается сигнал signalCheckItem, который содержит указатель на объект. В ядре игры проводится проверка. Если объект == apple, то выполняется удаление объекта.

void Widget::slotDeleteApple(QGraphicsItem *item)
{
    /* Получив сигнал от Мухи
     * Перебираем весь список яблок и удаляем найденное яблоко
     * */
    foreach (QGraphicsItem *apple, apples) {
        if(apple == item){
            scene->removeItem(apple);   // Удаляем со сцены
            apples.removeOne(item);     // Удаляем из списка
            delete apple;               // Вообще удаляем
            ui->lcdNumber->display(count++);    /* Увеличиваем счёт на единицу
                                                 * и отображаем на дисплее
                                                 * */
        }
    }
}
Зачем нам нужен список с указателями на все яблоки? Почему бы в ядре не выполнять код:
void Widget::slotDeleteApple(QGraphicsItem *item)
{
        if(apple == item){
            scene->removeItem(apple);
            delete apple; 
            ui->lcdNumber->display(count++);  
        }
    }
Еще вопрос. Зачем вызывать функцию removeItem, если вызывается оператор delete?
Evgenii Legotckoi
  • 24 травня 2017 р. 04:35
void Widget::slotDeleteApple(QGraphicsItem *item) 
{ 
    if(apple == item)
    { 
        scene->removeItem(apple); 
        delete apple; 
        ui->lcdNumber->display(count++); 
    } 
}

Подумайте немного над этим кодом, что вы привели, откуда вы возьмёте объект apple в вашем варианте кода, кроме как не из списка с указателями на яблоки? С данной архитектурой программы необходимо наличие списка с указателями на яблоки.

Что касается удаления, ну примените вы delete. И получите протухший указатель в самой графической сцене. Всё и везде чистить нужно.

L
  • 24 травня 2017 р. 04:58

А если применить приведение типов? Enemy01 *itemEnemy01 = dynamic_cast (item);

void Widget::slotDeleteApple(QGraphicsItem *item) 
{ 
 Apple *check = dynamic_cast<Apple *>(item);
    if(check)
    { 
        scene->removeItem(check); 
        delete check; 
        ui->lcdNumber->display(count++); 
    } 
}

Evgenii Legotckoi
  • 24 травня 2017 р. 05:12

Вот теперь, это будет правильнее. А теперь ответьте сами себе на вопрос. Много ли начинающих программистов, которые прочитали эту статью разбираются в приведении типов и множестве других нюансов? Вообще, можно было сделать удаление этих объектов и внутри графической сцены. И при этом стоит воспользоваться соответствующим кастом из Qt. То есть qgraphicsitem_cast и т.д. Или вообще создать специальный базовый класс, который будет иметь общий базовый метод, который будет возвращать тип объекта и уже по типу объекта принимать решение об удалении и т.д. Поскольку, если программа имеет слишком много кастов, то это тоже не очень хорошо и говорит о непродуманной архитектуре классов.

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
AD

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

  • Результат:50бали,
  • Рейтинг балів-4
m
  • molni99
  • 26 жовтня 2024 р. 01:37

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

  • Результат:80бали,
  • Рейтинг балів4
m
  • molni99
  • 26 жовтня 2024 р. 01:29

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

  • Результат:20бали,
  • Рейтинг балів-10
Останні коментарі
ИМ
Игорь Максимов22 листопада 2024 р. 11:51
Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii Legotckoi31 жовтня 2024 р. 14:37
Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZE19 жовтня 2024 р. 08:19
Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов05 жовтня 2024 р. 07:51
Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas505 липня 2024 р. 11:02
QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Тепер обговоріть на форумі
Evgenii Legotckoi
Evgenii Legotckoi24 червня 2024 р. 15:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey115 листопада 2024 р. 06:04
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProject04 червня 2022 р. 03:49
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9Anonim25 жовтня 2024 р. 09:10
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

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