Evgenii Legotckoi
Evgenii LegotckoiSept. 24, 2015, 10:56 a.m.

Qt/C++ - Lesson 021. The drawing mouse in Qt

In this lesson, let us learn drawing with the mouse in Qt, based on the most primitive analogue Paint using QGraphicsScene . No adjustments or brush size, or palette, or special effects, and a red line, which we will draw the mouse.

Project Structure

Project Structure The structure of the project consists of the following files:

  • paint.h - widget header file, which will be located a graphic scene to draw;
    paint.cpp - respectively the file source code for this widget;
    paintscene.h - customized header graphic scene, with which we work;
    paintscene.cpp - source file for customized graphic scene.

paint.ui

The form of the main window consists of the widget and placed it QGraphicsView object.

paint.h

This file is declared a customized graphical scene, as well as a timer with a slot for this timer, which is used for the correct processing of the application is resized.

#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;      // Define the timer for the preparation of the actual size of the graphic scenes          
    paintScene *scene;  // We declare a custom graphic scene

private:
    /* Override event resize the window to recalculate the size of the graphic scenes
     * */
    void resizeEvent(QResizeEvent * event);

private slots:
    void slotTimer();
};

#endif // PAINT_H

paint.cpp

In this class, there is the addition of customized graphic scene in a QGraphicsView class object, in fact for the purpose of learning the code of this part of the example has no special relationship to the process of drawing, but working out window resizing is included in this example for completeness. Needless drawing takes place exclusively in the customized graphic scene.

#include "paint.h"
#include "ui_paint.h"

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

    scene = new paintScene();       // Init graphics scene
    ui->graphicsView->setScene(scene);  // Set graphics scene
    timer = new QTimer();       // Init Timer
    connect(timer, &QTimer::timeout, this, &Paint::slotTimer);
    timer->start(100);          // Run Timer
}

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

void Paint::slotTimer()
{
    /* Recalculate the size of the graphic scenes, depending on the size of the window
     * */
    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

And here is the header file in this example. Drawing occurs via lines mouseMoveEvent by processing events. For this function is overridden mouseMoveEvent in which two coordinates, the first of a past event, and the second from the current, red lines are being built, which eventually form a common curve. But that when you release the mouse button is pressed again, we could draw a new line, rather than continuing the old, override function mousePressEvent.

In mousePressEvent drawn an ellipse, which is the starting point of drawing a curve with the mouse. This method updates the value of the first coordinate of the first line, thus tearing and separating from the new old curve. The video tutorial is demonstrated. the first point coordinates for the line is stored in previousPoint object.

#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;      // The coordinates of the previous point

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

};

#endif // PAINTSCENE_H

paintscene.cpp

In this file all the work with the drawing occurs in the methods and mouseMoveEvent mousePressEvent . While in the class constructor does not occur at any initialization.

#include "paintscene.h"

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

}

paintScene::~paintScene()
{

}

void paintScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    // When you press the mouse button, draw the ellipse
    addEllipse(event->scenePos().x() - 5,
               event->scenePos().y() - 5,
               10,
               10,
               QPen(Qt::NoPen),
               QBrush(Qt::red));
    // Save the coordinates of the point of pressing
    previousPoint = event->scenePos();
}

void paintScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    // We draw the line with the previous coordinates
    addLine(previousPoint.x(),
            previousPoint.y(),
            event->scenePos().x(),
            event->scenePos().y(),
            QPen(Qt::red,10,Qt::SolidLine,Qt::RoundCap));
    // Update on the previous coordinate data
    previousPoint = event->scenePos();
}

Result

As a result, you will be able to draw on graphics scene red lines, and how to further develop these possibilities already - it depends on you.

Рисование в Qt Archive with source project: Qt paint

Video

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

Р
  • Aug. 25, 2017, 4 a.m.

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

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

Evgenii Legotckoi
  • Aug. 25, 2017, 4:20 a.m.

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

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

#include <QGraphicsScene>
Р
  • Aug. 25, 2017, 6:04 a.m.

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

Evgenii Legotckoi
  • Aug. 25, 2017, 6:25 a.m.

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

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

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

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

Чтобы включить такое поведение, необходимо вызвать метод 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
  • May 11, 2018, 3:56 a.m.

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

Михаиллл
  • June 10, 2019, 2:43 a.m.
  • (edited)

Я задал в конструкторе 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
  • June 10, 2019, 3:52 a.m.

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

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

ИВ
  • April 28, 2020, 5:12 p.m.

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

Evgenii Legotckoi
  • April 28, 2020, 6:31 p.m.

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

f
  • Oct. 9, 2022, 6:40 p.m.
  • (edited)

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

f
  • Oct. 9, 2022, 9:18 p.m.

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

J
  • March 30, 2023, 11:57 a.m.

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

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

Evgenii Legotckoi
  • April 16, 2023, 4:03 a.m.

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

J
  • April 19, 2023, 5:18 a.m.
  • (edited)

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

Comments

Only authorized users can post comments.
Please, Log in or Sign up
l
  • laei
  • April 23, 2024, 3:19 p.m.

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:10points,
  • Rating points-10
l
  • laei
  • April 23, 2024, 3:17 p.m.

C++ - Тест 003. Условия и циклы

  • Result:50points,
  • Rating points-4
e
  • ehot
  • March 31, 2024, 8:29 p.m.

C++ - Тест 003. Условия и циклы

  • Result:78points,
  • Rating points2
Last comments
k
kmssrFeb. 9, 2024, 12:43 a.m.
Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVADec. 25, 2023, 4:30 p.m.
Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJoDec. 25, 2023, 2:38 p.m.
Boost - static linking in CMake project under Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
GvozdikDec. 19, 2023, 3:01 a.m.
Qt/C++ - Lesson 056. Connecting the Boost library in Qt for MinGW and MSVC compilers Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Now discuss on the forum
G
GarApril 22, 2024, 11:46 a.m.
Clipboard Как скопировать окно целиком в clipb?
DA
Dr Gangil AcademicsApril 20, 2024, 1:45 p.m.
Unlock Your Aesthetic Potential: Explore MSC in Facial Aesthetics and Cosmetology in India Embark on a transformative journey with an msc in facial aesthetics and cosmetology in india . Delve into the intricate world of beauty and rejuvenation, guided by expert faculty and …
a
a_vlasovApril 14, 2024, 12:41 p.m.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
Павел Дорофеев
Павел ДорофеевApril 14, 2024, 8:35 a.m.
QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
f
fastrexApril 4, 2024, 10:47 a.m.
Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…

Follow us in social networks