Evgenii Legotckoi
Evgenii Legotckoi21 сентября 2015 г. 10:44

Qt/C++ - Урок 020. QPainter - знакомство с рисованием в Qt

Во фреймворке Qt имеется возможность рисовать как на графической сцене , так и прямо на виджетах. Для этого используется класс QPainter. Рисование объектов на виджетах может производится в функции paintEvent(*event) , которая вызывается при отрисовке виджета.

В данном уроке будет производится работа именно с этой функцией. В ней будет создаваться объект класса QPainter, и с его помощью будет рисоваться круг. При этом рисование круга будет зависеть от трех объектов класса QRadioButton. В зависимости от того, какой радиобаттон выбран, будет выбираться и цвет круга, если же ни один радиобаттон не будет выбран, то круг будет рисоваться белого цвета.


Структура проекта для QPainter

Проект содержит следующие файлы:

  • painter.pro - профайл проекта;
  • widget.h - заголовочный файл класса, в котором и производится работа с QPainter;
  • widget.cpp - файл исходных кодов по работе с QPainter;
  • main.cpp - запускающий файл проекта;
  • widget.ui - интерфейс приложения.

widget.ui

В дизайнере форм добавляем в виджет GroupBox с радиобаттонами и вертикальный spacer.

Внешний вид приложения

widget.h

В данном файле только определяем метод paintEvent() .

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPainter>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

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

protected:
    /* Определяем виртуальный метод родительского класса
     * для отрисовки содержимого виджета
     * */
    void paintEvent(QPaintEvent *event);    

private slots:
    void on_radioButton_red_clicked();

    void on_radioButton_green_clicked();

    void on_radioButton_blue_clicked();

private:
    Ui::Widget *ui;

};

#endif // WIDGET_H

widget.cpp

А вот логика работы приложения полностью помещается в данный файл. В методе paintEvent() реализуем опрос радиобаттонов и по их состоянию рисуем круг на основном виджете.

#include "widget.h"
#include "ui_widget.h"

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

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

/* Метод, в котором происходит рисование
 * */
void Widget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter(this); // Создаём объект отрисовщика
    // Устанавливаем кисть абриса
    painter.setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::FlatCap));

    /* Проверяем, какой из радиобаттонов выбран
     * */
    if(ui->radioButton_red->isChecked()){
        // Если красный, то отрисовываем красный круг
        painter.setBrush(QBrush(Qt::red, Qt::SolidPattern));
        painter.drawEllipse(100, 50, 150, 150);
    } else if(ui->radioButton_green->isChecked()){
        // Если зелёный, то отрисовываем зеленый круг
        painter.setBrush(QBrush(Qt::green, Qt::SolidPattern));
        painter.drawEllipse(100, 50, 150, 150);
    } else if(ui->radioButton_blue->isChecked()){
        // Если синий, то отрисовываем синий круг
        painter.setBrush(QBrush(Qt::blue, Qt::SolidPattern));
        painter.drawEllipse(100, 50, 150, 150);
    } else {
        // Если ничего не выбрано, то отрисовываем белый круг
        painter.setBrush(QBrush(Qt::white, Qt::SolidPattern));
        painter.drawEllipse(100, 50, 150, 150);
    }
}

/* Как только один из радиобаттонов оказывается нажатым,
 * вызываем перерисовку содержимого виджета,
 * с которым работаем.
 * */
void Widget::on_radioButton_red_clicked()
{
    repaint();
}

void Widget::on_radioButton_green_clicked()
{
    repaint();
}

void Widget::on_radioButton_blue_clicked()
{
    repaint();
}

Итог

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

Архив с исходниками: painter

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

Вам это нравится? Поделитесь в социальных сетях!

И
  • 22 марта 2017 г. 12:12

Доброго времени суток. Подскажите, пожалуйста, следующую вещь: что такое private slots: void on_radioButton_red_clicked(); void on_radioButton_green_clicked(); void on_radioButton_blue_clicked(); Откуда они взялись??? Это какие - то предопределенные слоты класса radiobutton??? Почему они исполняются при нажатии переключателей??? Хоть убей, не пойму... Никакой инфы не нашел. Где они задаются привязанными к переключателям При попытке изменить имя слотов, они перестают работать... Сформулирую вопрос иначе: Где связываются переключатели и эти три слота???

И
  • 22 марта 2017 г. 12:19

Зы, т.е. если, я переименовываю слот, скажем,с void on_radioButton_blue_clicked() на void blue_clicked() в файлах widget.h и widget.cpp, все компилируется, но, переключатель radioButton_blue перестает работать ЗЫ: компилирую пример в Visual Studio. Creatorom и Designerom не пользуюсь... Эти слоты привязываются где - то в них?

Evgenii Legotckoi
  • 22 марта 2017 г. 13:02

Да. Совершенно верно. Данные слоты создаются через дизайнер. Если в дизайнере кликнуть правой кнопкой мыши на какой-то объект и выбрать создание слота clicked() , то будет выглядеть примерно так, как показано в примере.

Qt имеет этап предкомпиляции, когда создаются всякие мок файлы, и в данном случае привязка идёт по текстовому наименованию слота. Если слот не находится, то он не подключается во время компиляции.

Вы должны будете найти подключение этих слотов в ui_widget.h , который автоматически создаётя во время компиляции.

И
  • 22 марта 2017 г. 15:53

Понятно,спасибо,посмотрю...У нас,в виду исторических обстоятельств,весь код писан чисто в vs,без использования креатора(когда собирали qt под студии,креатор,даже,не компилировали),все интерфейсы писались через кодирование,и,все эти ui для меня темный лес... интересно расширить познания в этой области))

Evgenii Legotckoi
  • 22 марта 2017 г. 23:35

Проект, в котором я работаю на данный момент развивается уже более 5-ти лет. Я в нём работаю последние 8 месяцев. Интерфейс полностью написан на Ui, причём с использованием плагинов для Qt Designer, также над продуктом работает команда переводчиков. В продукте сотни диалоговых окон. И из своих наблюдений могу сказать, что если бы не использовались Ui, то в какой-то момент работать стало бы очень грустно, причём не только программистам, но и переводчикам, поскольку тот же самый Qt Linguist, поддерживает отображение Ui файлов, что гораздо удобнее, чем смотреть в код и не понимать, к какому всё-таки окну это относится.

И
  • 23 марта 2017 г. 3:16

У программы нас не имеют статических окошек, как таковых - окна могут быть совершенно различными в зависимости от множества условий, и, "лепятся", прямо, на лету, при запуске. Те, кто начинал проекты, выбрали чистый код, и, тем кто с ними работает сейчас, приходится делать все без использования ui, либо, все переписывать, а, это не на один год работы - проекты большие,ведутся лет 20, множество модулей написаны на всем, что можно только себе вообразить, начиная от ассемблера(работаем с железом и драйверами, в том числе) и заканчивая C#, и, все это завязано на кроссплатформенный qt, поскольку, поддерживается и Линупс. Старая команда отвалила, набрали новыю... Переписывать все жестоко, да, и, опыта у меня маловато

И
  • 23 марта 2017 г. 5:03

Увидел, еще, один интересный момент. Вы написали про редактирование слота clicked(), а, в дизайнере я этой возможности не нашел, но, тут такой момент... у меня qt собрана самостоятельно, без creator-a, есть, только, дизайнер. А, в дизайнере нет поддержки слотов(по правой клавише мыши). Потом, поставил Creator, а, там, дизайнер открывается в контексте проекта, вот, там создание слота clicked,уже есть... Про этот момент я не знал, поэтому, и, не нашел в дизайнере, как создать слот... В новых версиях qt создание слотов из дизайнера вынесли...

Evgenii Legotckoi
  • 23 марта 2017 г. 6:13

Но согласитесь, что отсутствие ui - это проблема того, что проекты давно развиваются, имеется много легаси кода и того, что на момента развития проектов и сам Qt не был так сильно развит. Например, Qt4 и Qt5 довольно сильно различаются, да даже Qt 5.6 очень отличается от Qt 5.8 по некоторым модулям, особенно если полезть в сторону QML. А после пары калымов я вовсе зарёкся браться за проекты с Qt4, особенно те, которые пишутся на устаревших версиях VS. Наверняка, многое можно стандартизировать и шаблонизировать. В нашем проекте сотни диалоговых окон с ui, но все они создаются и наполняются динамически. А также имеют всего несколько базовых классов. Просто различные вкладки интерфейса скрываются или добавляются в зависимости от этих самых условий, про которые вы сказали. Ну а так да. - Переписывать всё действительно жёстко, если проекты давно развиваются, но это уже немного другая история.

Evgenii Legotckoi
  • 23 марта 2017 г. 6:15

Думаю, что это вполне логичное развитие продукта. Без Креатора - это бесполезный функционал.

И
  • 23 марта 2017 г. 9:33

Это логично. Просто, именно, это ввело меня в ступор и заставило отписать в комментариях вчера. Причем, в дизайнере(который отдельно, открывается, без creator-a) есть редактор сигналов и слотов, но, он пуст. А, Creator-a у меня на тот момент не стояло

И
  • 24 марта 2017 г. 1:25

Соглашусь,там люди начинали с делфи,вообще,в свое время,когда все зарождалось потом,постепенно,постепенно,все облагораживалось,портировалось на более вменяемые средства разработки... Наши ребята-программисты(среди которых и я пятый помощник десятого стажера),говорят,что,ui вполне можно было использовать... у нас,еще,осложняется все тем,что,мы поддерживаем sdk,свои,на которой заказчики строят ПО,этих sdk несколько,если переписать,то,будет,еще на sdk больше,поскольку,старую никуда не денешь,а,заказчики консервативны.Сделали один раз и навсегда... у нас сфера промышленных систем,там еще компы на DOS,встречаются,до сих пор!!!)))))))

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
AD

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

  • Результат:50баллов,
  • Очки рейтинга-4
m
  • molni99
  • 26 октября 2024 г. 1:37

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

  • Результат:80баллов,
  • Очки рейтинга4
m
  • molni99
  • 26 октября 2024 г. 1:29

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

  • Результат:20баллов,
  • Очки рейтинга-10
Последние комментарии
ИМ
Игорь Максимов22 ноября 2024 г. 11:51
Django - Урок 017. Кастомизированная страница авторизации на Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii Legotckoi31 октября 2024 г. 14:37
Django - Урок 064. Как написать расширение для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZE19 октября 2024 г. 8:19
Читалка fb3-файлов на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов5 октября 2024 г. 7:51
Django - Урок 064. Как написать расширение для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55 июля 2024 г. 11:02
QML - Урок 016. База данных SQLite и работа с ней в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Сейчас обсуждают на форуме
m
moogo22 ноября 2024 г. 7:17
Mosquito Spray System Effective Mosquito Systems for Backyard | Eco-Friendly Misting Control Device & Repellent Spray - Moogo ; Upgrade your backyard with our mosquito-repellent device! Our misters conce…
Evgenii Legotckoi
Evgenii Legotckoi24 июня 2024 г. 15:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey115 ноября 2024 г. 6:04
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProject4 июня 2022 г. 3:49
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…

Следите за нами в социальных сетях