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 Т.Ж.
  • (өңделген)

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

Пікірлер

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

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 Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

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