Evgenii Legotckoi
Evgenii LegotckoiҚыр. 24, 2015, 10:56 Т.Ж.

Qt/C++ - Сабақ 021. Qt тілінде тінтуірмен сурет салу

Бұл сабақта біз QGraphicsScene көмегімен Paint бағдарламасының ең қарапайым аналогы негізінде Qt тілінде тінтуірмен сурет салуды меңгереміз. Ешқандай түзетулер, қылқалам өлшемдері, палитра жоқ, арнайы әсерлер жоқ, біз тінтуірмен сызатын қызыл сызық.

Міндет қойылды – орындауға алға!

Жоба құрылымы

Жоба құрылымы Жоба құрылымы келесі файлдарды қамтиды:

  • paint.h – сурет салуға арналған графикалық көріністі қамтитын виджеттің тақырыптық файлы;
  • paint.cpp - сәйкесінше осы виджет үшін бастапқы код файлы;
  • paintscene.h - біз жұмыс істейтін теңшелген графикалық көріністің тақырып файлы;
  • paintscene.cpp - реттелетін графикалық көріністің бастапқы код файлы.

paint.ui

Негізгі қолданба терезесінің пішіні виджеттің өзінен және оған орналастырылған QGraphicsView. нысанынан тұрады.

paint.h

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

#ifndef PAINT\_H
#define PAINT\_H

#include <QWidget>
#include <QTimer>
#include <QResizeEvent>

#include <paintscene.h>

namespace Ui {
class Paint;
}

class Paint : public QWidget
{
    Q\_OBJECT

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

private:
    Ui::Paint *ui;
    QTimer *timer;      /* Определяем таймер для подготовки актуальных размеров
                         * графической сцены
                         * */
    paintScene *scene;  // Объявляем кастомную графическую сцену

private:
    /* Переопределяем событие изменения размера окна
     * для пересчёта размеров графической сцены
     * */
    void resizeEvent(QResizeEvent * event);

private slots:
    void slotTimer();
};

#endif // PAINT\_H

paint.cpp

Бұл сыныпта QGraphicsView класының объектісіне теңшелген графикалық көрініс қосылады, шын мәнінде, оқыту мақсатында мысалдың осы бөлігіндегі бағдарлама кодының сурет салу процесінің өзіне көп қатысы жоқ, бірақ толықтық үшін терезе өлшемін өзгерту осы мысалда қамтылған. Сызбаның өзі тек теңшелген графикалық көріністе орын алады.

#include "paint.h"
#include "ui\_paint.h"

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

    scene = new paintScene();       // Инициализируем графическую сцену
    ui->graphicsView->setScene(scene);  // Устанавливаем графическую сцену

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

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

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

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

paintscene.h

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

mousePressEvent бағдарламасында тінтуірдің көмегімен қисық сызу үшін бастапқы нүкте ретінде қызмет ететін эллипс сызылады. Бұл әдіс бірінші жолдың бірінші координат мәндерін жаңартады, осылайша ескі қисықты жаңадан үзіп, ажыратады. Бұл бейне оқулықта көрсетілген. Жолдың бірінші координат нүктесі previousPoint. нысанында сақталады

#ifndef PAINTSCENE\_H
#define PAINTSCENE\_H

#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QTimer>
#include <QDebug>

class paintScene : public QGraphicsScene
{

    Q\_OBJECT

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

private:
    QPointF     previousPoint;      // Координаты предыдущей точки

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

};

#endif // PAINTSCENE\_H

paintscene.cpp

Бұл файлда суретпен барлық жұмыс mouseMoveEvent және mousePressEvent. әдістерінде орындалады, ал класс конструкторында инициализация мүлде болмайды.

#include "paintscene.h"

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

}

paintScene::~paintScene()
{

}

void paintScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    // При нажатии кнопки мыши отрисовываем эллипс
    addEllipse(event->scenePos().x() - 5,
               event->scenePos().y() - 5,
               10,
               10,
               QPen(Qt::NoPen),
               QBrush(Qt::red));
    // Сохраняем координаты точки нажатия
    previousPoint = event->scenePos();
}

void paintScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    // Отрисовываем линии с использованием предыдущей координаты
    addLine(previousPoint.x(),
            previousPoint.y(),
            event->scenePos().x(),
            event->scenePos().y(),
            QPen(Qt::red,10,Qt::SolidLine,Qt::RoundCap));
    // Обновляем данные о предыдущей координате
    previousPoint = event->scenePos();
}

Барлығы

Нәтижесінде сіз графикалық көрініске қызыл сызықтар сала аласыз және бұл мүмкіндіктерді одан әрі дамыту сізге байланысты.

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

Жобаның бастапқы коды бар Qt мұрағатындағы кескіндеме: Qt paint

Qt тілінде сурет салу туралы бейне оқулық

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

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

Р
  • Там. 25, 2017, 4 Т.Ж.

Здравствуйте! Спасибо за подробное описание данного примера, а вы бы не могли показать, что все это время происходило в main.cpp?
Потому что при использовании данного примера я получила ошибку:

321: ошибка: 'addLine' was not declared in this scope
QPen(Qt::red,10,Qt::SolidLine));
^
И я просто не могу понять, что же не так?

Evgenii Legotckoi
  • Там. 25, 2017, 4:20 Т.Ж.

Добрый день!
main.cpp остаётся созданным по умолчанию, там ничего интересного для Вас нет.
А ошибка говорит о том, что у Вас отсутствует необходимый заголовочный файл, вернее его подключение.

Думаю, что Вы пропустили следующий include

#include <QGraphicsScene>
Р
  • Там. 25, 2017, 6:04 Т.Ж.

Нет, не пропустила, есть инклюд
Полагаю, ошибка в вызове в главном окне этой сцены.
Или в чем-то еще, ибо он не заходит в эту библиотеку и соотвественно не видит addline

Evgenii Legotckoi
  • Там. 25, 2017, 6:25 Т.Ж.

то есть вызываете этот метод так?

void mainWindow::someMethod()
{
    graphicsScene->addLine();
}
Вообще такая ошибка говорит о том, что метод или функция не объявлены, а это значит зачастую, что пропущен необходимый инклюд.
a
  • Мамыр 11, 2018, 2:28 Т.Ж.

А почему mouseMoveEvent() выполняется лишь при на нажатой кнопки мыши?

По сигнатуре функции я предположил, что метод должен вызываться сценой при простом движением мышки по сцене.
Evgenii Legotckoi
  • Мамыр 11, 2018, 3:10 Т.Ж.

Чтобы включить такое поведение, необходимо вызвать метод setMouseTracking(true) у QGraphicsView, в котором расположена графическая сцена, тогда события движения мыши должны передаваться при движении курсора как с нажатыми клавишами мыши, так и без.


Paint::Paint(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Paint)
{
    ui->setupUi(this);
 
    scene = new paintScene();       
    ui->graphicsView->setScene(scene);  
    ui->graphicsView->setMouseTracking(true);
 
}
a
  • Мамыр 11, 2018, 3:56 Т.Ж.

Спасибо, попробовал. Работает )

Михаиллл
  • Маусым 10, 2019, 2:43 Т.Ж.
  • (өңделген)

Я задал в конструкторе Paint картинку на лэйбел. Скажите пожалуйста, как рисовать на mapImage.

    QImage mapImage("C:\\Users\\New Owner\\Downloads\\mapMain.png");
    ui->label->setPixmap(QPixmap::fromImage(mapImage,Qt::AutoColor));

и я унаследовал клас рисовальщик так, но в нем нет таких сигналов, какие используется в .срр:

class paintScene : public QLabel
Evgenii Legotckoi
  • Маусым 10, 2019, 3:52 Т.Ж.

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

И естественно, что там не будет тех сигналов и методов, потому что PaintScene нужно наследовать от QGraphicsScene. Рисовать нужно на графической сцене.

ИВ
  • Сәуір 28, 2020, 5:12 Т.Қ.

Добрый день. Извините за нюбский вопрос.
Данный проект у меня работает, что вызвало удивление. Так как я не нашел слотов, принимающих события от void mousePressEvent(QGraphicsSceneMouseEvent * event); и void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
Я пока разбираюсь со слотами, обьясните пожалуйста - выходит если сигнал (в данном случае событие) описан внутри класса, то для обьектов класса слот не нужен ?

Evgenii Legotckoi
  • Сәуір 28, 2020, 6:31 Т.Қ.

Добрый день. Это переопределённые методы из базового класса, они не являются слотами и вызываются в очереди событий внутри ядра Qt фреймворка. В обычном программировании на Qt никто не ищет откуда они конкретно вызываются. Для этого нужно копаться в исходниках Qt. То есть сигнала нет внутри класса и сигналы нужны для слотов, но в данном конкретном случае к вызову этих методов обобщённо говоря сигналы отношения не имеют.

f
  • Қаз. 9, 2022, 6:40 Т.Қ.
  • (өңделген)

Здравствуйте! Не понимаю в чем проблема, ui(new Ui::Paint) обозначается как недопустимый неполный тип и программа не запускается. Уже скопировал тупо только ваш код без собственных фрагментов, но все та же проблема. Помогите пожалуйста, срочно! Программирую в среде Visual Studio 2019.

f
  • Қаз. 9, 2022, 9:18 Т.Қ.

upd: все исправил

J
  • Наурыз 30, 2023, 11:57 Т.Ж.

Евгений, здравствуйте! Только начал изучение Qt и возник вопрос по 21ому уроку. После написания кода, выдаёт следующие ошибки

В чём может быть проблема?

Evgenii Legotckoi
  • Сәуір 16, 2023, 4:03 Т.Ж.

В UI файле не был добавлен QGraphicsView объект с object name graphicsView

J
  • Сәуір 19, 2023, 5:18 Т.Ж.
  • (өңделген)

Евгений, исправил: благодарю! Всё работает!

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
OI
  • Ora Iro
  • Жел. 24, 2024, 6:38 Т.Ж.

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

  • Нәтиже:40ұпай,
  • Бағалау ұпайлары-8
AD

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

  • Нәтиже:50ұпай,
  • Бағалау ұпайлары-4
m
  • molni99
  • Қаз. 26, 2024, 1:37 Т.Ж.

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

  • Нәтиже:80ұпай,
  • Бағалау ұпайлары4
Соңғы пікірлер
ИМ
Игорь МаксимовҚар. 22, 2024, 11:51 Т.Ж.
Django - Оқулық 017. Теңшелген Django кіру беті Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii LegotckoiҚаз. 31, 2024, 2:37 Т.Қ.
Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZEҚаз. 19, 2024, 8:19 Т.Ж.
Qt Creator көмегімен fb3 файл оқу құралы Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь МаксимовҚаз. 5, 2024, 7:51 Т.Ж.
Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey1Қар. 15, 2024, 6:04 Т.Ж.
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProjectМаусым 4, 2022, 3:49 Т.Ж.
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9AnonimҚаз. 25, 2024, 9:10 Т.Ж.
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

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