Бұл сабақта біз 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
Здравствуйте! Спасибо за подробное описание данного примера, а вы бы не могли показать, что все это время происходило в main.cpp?
Потому что при использовании данного примера я получила ошибку:
321: ошибка: 'addLine' was not declared in this scope
QPen(Qt::red,10,Qt::SolidLine));
^
И я просто не могу понять, что же не так?
Добрый день!
main.cpp остаётся созданным по умолчанию, там ничего интересного для Вас нет.
А ошибка говорит о том, что у Вас отсутствует необходимый заголовочный файл, вернее его подключение.
Думаю, что Вы пропустили следующий include
Нет, не пропустила, есть инклюд
Полагаю, ошибка в вызове в главном окне этой сцены.
Или в чем-то еще, ибо он не заходит в эту библиотеку и соотвественно не видит addline
то есть вызываете этот метод так?
Вообще такая ошибка говорит о том, что метод или функция не объявлены, а это значит зачастую, что пропущен необходимый инклюд.А почему mouseMoveEvent() выполняется лишь при на нажатой кнопки мыши?
Чтобы включить такое поведение, необходимо вызвать метод setMouseTracking(true) у QGraphicsView, в котором расположена графическая сцена, тогда события движения мыши должны передаваться при движении курсора как с нажатыми клавишами мыши, так и без.
Спасибо, попробовал. Работает )
Я задал в конструкторе Paint картинку на лэйбел. Скажите пожалуйста, как рисовать на mapImage.
и я унаследовал клас рисовальщик так, но в нем нет таких сигналов, какие используется в .срр:
Вообще не понимаю, зачем вы используете QLabel для этого. Используйте графическую сцену и рисуйте на ней. QLabel был написан для отображения текста и картинок, но никак не для рисования.
И естественно, что там не будет тех сигналов и методов, потому что PaintScene нужно наследовать от QGraphicsScene. Рисовать нужно на графической сцене.
Добрый день. Извините за нюбский вопрос.
Данный проект у меня работает, что вызвало удивление. Так как я не нашел слотов, принимающих события от void mousePressEvent(QGraphicsSceneMouseEvent * event); и void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
Я пока разбираюсь со слотами, обьясните пожалуйста - выходит если сигнал (в данном случае событие) описан внутри класса, то для обьектов класса слот не нужен ?
Добрый день. Это переопределённые методы из базового класса, они не являются слотами и вызываются в очереди событий внутри ядра Qt фреймворка. В обычном программировании на Qt никто не ищет откуда они конкретно вызываются. Для этого нужно копаться в исходниках Qt. То есть сигнала нет внутри класса и сигналы нужны для слотов, но в данном конкретном случае к вызову этих методов обобщённо говоря сигналы отношения не имеют.
Здравствуйте! Не понимаю в чем проблема, ui(new Ui::Paint) обозначается как недопустимый неполный тип и программа не запускается. Уже скопировал тупо только ваш код без собственных фрагментов, но все та же проблема. Помогите пожалуйста, срочно! Программирую в среде Visual Studio 2019.
upd: все исправил
Евгений, здравствуйте! Только начал изучение Qt и возник вопрос по 21ому уроку. После написания кода, выдаёт следующие ошибки
В чём может быть проблема?
В UI файле не был добавлен QGraphicsView объект с object name graphicsView
Евгений, исправил: благодарю! Всё работает!