Как сделать paint в qt
Теперь приступим к рисовании сетки. Надо заметить, что первоначально представлялось, что метки надо рисовать вместе с координатными линиями. Однако такой подход идет вразрез с декларативной идеологией фреймворка: описать как в простейшем случае должен выглядеть item, а затем рассказать сцене как она должна с ним поступать, и на выходе получить идеальную картинку в любых условиях. И в итоге верстка засечек была перенесена в compose.
- Нам достаточно рисовать линии графика в шкале данных. Они сами отобразятся в нужную область, а если добавитьто решается проблема кадрирования графика
- Все события сцены (такие как события клавиатуры или события мыши автоматически будут переводится в шкалу данных, что упрощает их обработку.
Тут есть один тонкий момент: при увеличении с помощью QTransform нашего gridItem размер кисти тоже растет, чтоб этого не происходило необходимо задать QPen как cosmetic:
Item графика
Реализация графика чрезвычайно простая и большую часть кода занимает выяснение границ boundRect.
Легенда и взаимодействие классов
На самом деле у нас уже есть решение, оно очевидно, если обратить внимание, что GraphicsDataItem отнаследован от QGraphicsObject и что в теле класса уже объявлены сигналы. Т.е. взаимодействие между объектами сцены происходит привычным образом — через сигналы и слоты.
Субъективный итог
- Беспроблемность разработки архитектуры, если следовать логике фреймворка.
- Все элементы написаны в декларативном стиле и основной код относится к сути и в значительной меньшей мере к пляскам вокруг.
- Простата создания item-ов для отображения данных
Сравнение и калибровка по qwt.
- Первое, что бросается в глаза — огромные листинги в drawItem. Наши на порядок короче. Нам не надо заботиться об оптимизации отрисовки каждого члена. Мы делаем один раз и в одном месте — когда задаем viewport..
- Куча трудов вложено в QwtLegendData, QwtLegendLabel, QwtPainter, QwtPainterCommand, QwtPlotDirectPainter и т.д. Мы всего это не делали и не ясны причины зачем в нашей ситуации все это реализовывать.
- Нам не надо писать свои классы трансформации и пересчета координат из одной системы в другую, и нам не надо вручную производить трансформацию координат.
- Мы добились гораздо большей абстрагированности iem-ов с данными.
- Наша иерархия классов на порядок проще. И при дальнейшем расширении не видно причин, почему она должна стать сложнее.
Ссылки
Документация, развернутая с примерами.
Видео, если нельзя скачать с офф сайта, то спокойно находятся на youtube
Проект.
P.S. Проект демонстрационный, но если будут найдены баги, или кто поможет с улучшением — буду только рад.
P.P.S На всякий случай: текст опубликован под лицензией CC-BY 3.0
UPD итог полустараний:
Во фреймворке Qt имеется возможность рисовать как на графической сцене , так и прямо на виджетах. Для этого используется класс QPainter. Рисование объектов на виджетах может производится в функции paintEvent(*event) , которая вызывается при отрисовке виджета.
В данном уроке будет производится работа именно с этой функцией. В ней будет создаваться объект класса QPainter, и с его помощью будет рисоваться круг. При этом рисование круга будет зависеть от трех объектов класса QRadioButton. В зависимости от того, какой радиобаттон выбран, будет выбираться и цвет круга, если же ни один радиобаттон не будет выбран, то круг будет рисоваться белого цвета.
- 1. Структура проекта для QPainter
- 2. widget.ui
- 3. widget.h
- 4. widget.cpp
- 5. Итог
Структура проекта для QPainter
Проект содержит следующие файлы:
- painter.pro - профайл проекта;
- widget.h - заголовочный файл класса, в котором и производится работа с QPainter;
- widget.cpp - файл исходных кодов по работе с QPainter;
- main.cpp - запускающий файл проекта;
- widget.ui - интерфейс приложения.
widget.ui
В дизайнере форм добавляем в виджет GroupBox с радиобаттонами и вертикальный spacer.
Внешний вид приложения
widget.h
В данном файле только определяем метод paintEvent() .
widget.cpp
А вот логика работы приложения полностью помещается в данный файл. В методе paintEvent() реализуем опрос радиобаттонов и по их состоянию рисуем круг на основном виджете.
В результате у Вас получится приложение, показанное на ниже следующем рисунке. Демонстрация работы приложения присутствует в видеоуроке по данной статье.
Архив с исходниками: painter
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
Рекомендуемые статьи по этой тематике
По статье задано2 вопрос(ов)
Подписчики
Платёжная система
Доброго времени суток. Подскажите, пожалуйста, следующую вещь: что такое private slots: void on_radioButton_red_clicked(); void on_radioButton_green_clicked(); void on_radioButton_blue_clicked(); Откуда они взялись. Это какие - то предопределенные слоты класса radiobutton. Почему они исполняются при нажатии переключателей. Хоть убей, не пойму. Никакой инфы не нашел. Где они задаются привязанными к переключателям При попытке изменить имя слотов, они перестают работать. Сформулирую вопрос иначе: Где связываются переключатели и эти три слота.
Зы, т.е. если, я переименовываю слот, скажем,с void on_radioButton_blue_clicked() на void blue_clicked() в файлах widget.h и widget.cpp, все компилируется, но, переключатель radioButton_blue перестает работать ЗЫ: компилирую пример в Visual Studio. Creatorom и Designerom не пользуюсь. Эти слоты привязываются где - то в них?
Да. Совершенно верно. Данные слоты создаются через дизайнер. Если в дизайнере кликнуть правой кнопкой мыши на какой-то объект и выбрать создание слота clicked() , то будет выглядеть примерно так, как показано в примере.
Qt имеет этап предкомпиляции, когда создаются всякие мок файлы, и в данном случае привязка идёт по текстовому наименованию слота. Если слот не находится, то он не подключается во время компиляции.
Вы должны будете найти подключение этих слотов в ui_widget.h , который автоматически создаётя во время компиляции.
Понятно,спасибо,посмотрю. У нас,в виду исторических обстоятельств,весь код писан чисто в vs,без использования креатора(когда собирали qt под студии,креатор,даже,не компилировали),все интерфейсы писались через кодирование,и,все эти ui для меня темный лес. интересно расширить познания в этой области))
Проект, в котором я работаю на данный момент развивается уже более 5-ти лет. Я в нём работаю последние 8 месяцев. Интерфейс полностью написан на Ui, причём с использованием плагинов для Qt Designer, также над продуктом работает команда переводчиков. В продукте сотни диалоговых окон. И из своих наблюдений могу сказать, что если бы не использовались Ui, то в какой-то момент работать стало бы очень грустно, причём не только программистам, но и переводчикам, поскольку тот же самый Qt Linguist, поддерживает отображение Ui файлов, что гораздо удобнее, чем смотреть в код и не понимать, к какому всё-таки окну это относится.
Увидел, еще, один интересный момент. Вы написали про редактирование слота clicked(), а, в дизайнере я этой возможности не нашел, но, тут такой момент. у меня qt собрана самостоятельно, без creator-a, есть, только, дизайнер. А, в дизайнере нет поддержки слотов(по правой клавише мыши). Потом, поставил Creator, а, там, дизайнер открывается в контексте проекта, вот, там создание слота clicked,уже есть. Про этот момент я не знал, поэтому, и, не нашел в дизайнере, как создать слот. В новых версиях qt создание слотов из дизайнера вынесли.
Но согласитесь, что отсутствие ui - это проблема того, что проекты давно развиваются, имеется много легаси кода и того, что на момента развития проектов и сам Qt не был так сильно развит. Например, Qt4 и Qt5 довольно сильно различаются, да даже Qt 5.6 очень отличается от Qt 5.8 по некоторым модулям, особенно если полезть в сторону QML. А после пары калымов я вовсе зарёкся браться за проекты с Qt4, особенно те, которые пишутся на устаревших версиях VS. Наверняка, многое можно стандартизировать и шаблонизировать. В нашем проекте сотни диалоговых окон с ui, но все они создаются и наполняются динамически. А также имеют всего несколько базовых классов. Просто различные вкладки интерфейса скрываются или добавляются в зависимости от этих самых условий, про которые вы сказали. Ну а так да. - Переписывать всё действительно жёстко, если проекты давно развиваются, но это уже немного другая история.
А в этом уроке освоим рисование мышью в Qt на основе примитивнейшего аналога Paint с использованием QGraphicsScene . Никаких регулировок, ни размеров кисти, ни палитры, ни спецэффектов, а просто красная линия, которую мы будем рисовать мышью.
Задача поставлена - вперёд исполнять!
Структура проекта
Структура проекта В структуру проекта входят следующие файлы:
- paint.h - заголовочный файл виджета, в котором будет располагаться графическая сцена для рисования;
- paint.cpp - соответственно файл исходных кодов для этого виджета;
- paintscene.h - заголовочный файл кастомизированной графической сцены, с которой мы будем работать;
- paintscene.cpp - файл исходных кодов кастомизированной графической сцены.
- 1. Структура проекта
- 2. paint.ui
- 3. paint.h
- 4. paint.cpp
- 5. paintscene.h
- 6. paintscene.cpp
- 7. Итог
- 8. Видеоурок про рисование в Qt
paint.ui
Форма главного окна приложения состоит из самого виджета и помещенного в него объекта QGraphicsView.
paint.h
В данном файле объявляется кастомизированная графическая сцена, а также таймер со слотом для этого таймера, который служит для корректной обработки изменения размеров окна приложения.
paint.cpp
В данном классе происходит добавление кастомизированной графической сцены в объект класса QGraphicsView , фактически в целях обучения программный код из данной части примера не имеет особого отношения к самому процессу рисования, но отработка изменения размеров окна включена в данный пример для полноты картины. Само рисование происходит исключительно в кастомизированной графической сцене.
paintscene.h
А вот и заголовочный файл виновника данного примера. Рисование происходит с помощью линий, посредством обработки события mouseMoveEvent. Для этого переопределяется функция mouseMoveEvent в которой по двум координатам, первая от прошлого события и вторая от текущего, строятся красные линии, которые в итоге образуют общую кривую. Но чтобы при отпускании кнопки мыши и повторном нажатии мы могли рисовать новую линию, а не продолжать старую, переопределяем функцию mousePressEvent.
В mousePressEvent отрисовывается эллипс, который служит стартовой точкой рисования кривой мышью. Этот метод обновляет значения первой координаты для первой линии, таким образом разрывая и отделяя старую кривую от новой. В видеоуроке это продемонстрировано. Точка первой координаты для линии сохраняется в объект previousPoint.
paintscene.cpp
В данном файле вся работа с рисованием происходит в методах mouseMoveEvent и mousePressEvent. Тогда как в конструкторе класса вообще не происходит какой-либо инициализации.
В результате Вы сможете рисовать на графической сцене красные линии, а как дальше уже развить эти возможности - это уже зависит от Вас.
Также вы можете ознакомиться с комментариями и демонстрацией проекта в видеоуроке по данной статье.
Рисование в Qt Архив с исходным кодом проекта: Qt paint
Видеоурок про рисование в Qt
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
In Qt framework you have gat opportunity to draw on the graphics scene and widgets. For it you can use QPainter class. Drawing objects on the widgets can be made in paintEvent (* event) function that is called when rendering the widget.
In this tutorial you will work with this function. It will create an object of class QPainter , and with it will be drawn circle. At the same time drawing a circle will depend on three QRadioButton object class. Depending on what radiobatton selected will be selected and the color of circle, if none radiobatton is selected, then the circle is drawn in white.
- 1. Project structure for QPainter
- 2. widget.ui
- 3. widget.h
- 4. widget.cpp
- 5. Result
Project structure for QPainter
Project contains the following files:
- painter.pro - project profile;
- widget.h - header file of Widget class, which will works with QPainter;
- widget.cpp - source file of Widget class, which will works with QPainter;
- main.cpp - file with main function;
- widget.ui - application interface
widget.ui
In the form designer to add the widget to the GroupBox with Radio Buttons and vertical spacer.
widget.h
In this file you have to define paintEvent() .
widget.cpp
But the logic of the application works completely placed in this file. In paintEvent() method will implement the handlers of radio buttons and they draw a circle of the main widget.
Result
As a result, you get the app, as shown in the following figure. Demonstration application is present in the video tutorial on this article.
Archive with source: painter
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Recommended articles on this topic
By article asked2 question(s)
Subscribers
Payment system
Доброго времени суток. Подскажите, пожалуйста, следующую вещь: что такое private slots: void on_radioButton_red_clicked(); void on_radioButton_green_clicked(); void on_radioButton_blue_clicked(); Откуда они взялись. Это какие - то предопределенные слоты класса radiobutton. Почему они исполняются при нажатии переключателей. Хоть убей, не пойму. Никакой инфы не нашел. Где они задаются привязанными к переключателям При попытке изменить имя слотов, они перестают работать. Сформулирую вопрос иначе: Где связываются переключатели и эти три слота.
Зы, т.е. если, я переименовываю слот, скажем,с void on_radioButton_blue_clicked() на void blue_clicked() в файлах widget.h и widget.cpp, все компилируется, но, переключатель radioButton_blue перестает работать ЗЫ: компилирую пример в Visual Studio. Creatorom и Designerom не пользуюсь. Эти слоты привязываются где - то в них?
Да. Совершенно верно. Данные слоты создаются через дизайнер. Если в дизайнере кликнуть правой кнопкой мыши на какой-то объект и выбрать создание слота clicked() , то будет выглядеть примерно так, как показано в примере.
Qt имеет этап предкомпиляции, когда создаются всякие мок файлы, и в данном случае привязка идёт по текстовому наименованию слота. Если слот не находится, то он не подключается во время компиляции.
Вы должны будете найти подключение этих слотов в ui_widget.h , который автоматически создаётя во время компиляции.
Понятно,спасибо,посмотрю. У нас,в виду исторических обстоятельств,весь код писан чисто в vs,без использования креатора(когда собирали qt под студии,креатор,даже,не компилировали),все интерфейсы писались через кодирование,и,все эти ui для меня темный лес. интересно расширить познания в этой области))
Проект, в котором я работаю на данный момент развивается уже более 5-ти лет. Я в нём работаю последние 8 месяцев. Интерфейс полностью написан на Ui, причём с использованием плагинов для Qt Designer, также над продуктом работает команда переводчиков. В продукте сотни диалоговых окон. И из своих наблюдений могу сказать, что если бы не использовались Ui, то в какой-то момент работать стало бы очень грустно, причём не только программистам, но и переводчикам, поскольку тот же самый Qt Linguist, поддерживает отображение Ui файлов, что гораздо удобнее, чем смотреть в код и не понимать, к какому всё-таки окну это относится.
Увидел, еще, один интересный момент. Вы написали про редактирование слота clicked(), а, в дизайнере я этой возможности не нашел, но, тут такой момент. у меня qt собрана самостоятельно, без creator-a, есть, только, дизайнер. А, в дизайнере нет поддержки слотов(по правой клавише мыши). Потом, поставил Creator, а, там, дизайнер открывается в контексте проекта, вот, там создание слота clicked,уже есть. Про этот момент я не знал, поэтому, и, не нашел в дизайнере, как создать слот. В новых версиях qt создание слотов из дизайнера вынесли.
Но согласитесь, что отсутствие ui - это проблема того, что проекты давно развиваются, имеется много легаси кода и того, что на момента развития проектов и сам Qt не был так сильно развит. Например, Qt4 и Qt5 довольно сильно различаются, да даже Qt 5.6 очень отличается от Qt 5.8 по некоторым модулям, особенно если полезть в сторону QML. А после пары калымов я вовсе зарёкся браться за проекты с Qt4, особенно те, которые пишутся на устаревших версиях VS. Наверняка, многое можно стандартизировать и шаблонизировать. В нашем проекте сотни диалоговых окон с ui, но все они создаются и наполняются динамически. А также имеют всего несколько базовых классов. Просто различные вкладки интерфейса скрываются или добавляются в зависимости от этих самых условий, про которые вы сказали. Ну а так да. - Переписывать всё действительно жёстко, если проекты давно развиваются, но это уже немного другая история.
Qt's paint system enables painting on screen and print devices using the same API, and is primarily based on the QPainter, QPaintDevice, and QPaintEngine classes.
QPainter is used to perform drawing operations, QPaintDevice is an abstraction of a two-dimensional space that can be painted on using a QPainter, and QPaintEngine provides the interface that the painter uses to draw onto different types of devices. The QPaintEngine class is used internally by QPainter and QPaintDevice, and is hidden from application programmers unless they create their own device type.
The main benefit of this approach is that all painting follows the same painting pipeline making it easy to add support for new features and providing default implementations for unsupported ones.
Topics
Classes for Painting
These classes provide support for painting onto a paint device.
Monochrome (1-bit depth) pixmaps
Defines the fill pattern of shapes drawn by QPainter
Colors based on RGB, HSV or CMYK values
Color space abstraction
Transformation between color spaces
Maps device independent QColors to device dependent pixel values
Used in combination with QBrush to specify a conical gradient brush
Specifies a query for a font used for drawing text
Font metrics information
Font metrics information
Template class that represents a NxM transformation matrix with N columns and M rows
Used in combination with QBrush to specify gradient fills
Scalable icons in different modes and states
Abstract base class for QIcon renderers
Hardware-independent image representation that allows direct access to the pixel data, and can be used as a paint device
Format independent interface for reading images from files or other devices
Format independent interface for writing images to files or other devices
Two-dimensional vector using integer precision
Two-dimensional vector using floating point precision
Used in combination with QBrush to specify a linear gradient brush
Defines the four margins of a rectangle
Defines the four margins of a rectangle
Represents a paint device that supports multiple pages
The base class of objects that can be painted on with QPainter
Abstract definition of how QPainter draws to a given device on a given platform
Performs low-level painting on widgets and other paint devices
Container for painting operations, enabling graphical shapes to be constructed and reused
Used to generate fillable outlines for a given painter path
Class to generate PDFs that can be used as a paint device
Defines how a QPainter should draw lines and outlines of shapes
Off-screen image representation that can be used as a paint device
Defines a point in the plane using integer precision
Defines a point in the plane using floating point precision
Vector of points using integer precision
Vector of points using floating point precision
Used in combination with QBrush to specify a radial gradient brush
Defines a rectangle in the plane using integer precision
Defines a rectangle in the plane using floating point precision
Specifies a clip region for a painter
Struct contains a 64-bit RGB color
Defines the size of a two-dimensional object using integer point precision
Defines the size of a two-dimensional object using floating point precision
Convenience class for drawing QStyle elements inside a widget
Used when registering fonts with the internal Qt fontdatabase
Paint device that is used to create SVG drawings
Used to draw the contents of SVG files onto paint devices
Widget that is used to display the contents of Scalable Vector Graphics (SVG) files
Specifies 2D transformations of a coordinate system
Represents a vector or vertex in 2D space
© 2022 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.
Читайте также: