Evgenii Legotckoi
21 вересня 2015 р. 20: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() .

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3.  
  4. #include <QWidget>
  5. #include <QPainter>
  6.  
  7. namespace Ui {
  8. class Widget;
  9. }
  10.  
  11. class Widget : public QWidget
  12. {
  13. Q_OBJECT
  14.  
  15. public:
  16. explicit Widget(QWidget *parent = 0);
  17. ~Widget();
  18.  
  19. protected:
  20. /* Визначаємо віртуальний метод батьківського класу для відтворення вмісту віджета */
  21. void paintEvent(QPaintEvent *event);
  22.  
  23. private slots:
  24. void on_radioButton_red_clicked();
  25.  
  26. void on_radioButton_green_clicked();
  27.  
  28. void on_radioButton_blue_clicked();
  29.  
  30. private:
  31. Ui::Widget *ui;
  32.  
  33. };
  34.  
  35. #endif // WIDGET_H

widget.cpp

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

  1. #include "widget.h"
  2. #include "ui_widget.h"
  3.  
  4. Widget::Widget(QWidget *parent) :
  5. QWidget(parent),
  6. ui(new Ui::Widget)
  7. {
  8. ui->setupUi(this);
  9. }
  10.  
  11. Widget::~Widget()
  12. {
  13. delete ui;
  14. }
  15.  
  16. /* Метод, в якому відбувається малювання
  17. * */
  18. void Widget::paintEvent(QPaintEvent *event)
  19. {
  20. Q_UNUSED(event);
  21. QPainter painter(this); // Створюємо об'єкт відтворення
  22. // Встановлюємо кисть абрису
  23. painter.setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::FlatCap));
  24.  
  25. /* Перевіряємо, який з радіобаттон обраний
  26. * */
  27. if(ui->radioButton_red->isChecked()){
  28. // Якщо червоний, то отрісовиваємих червоне коло
  29. painter.setBrush(QBrush(Qt::red, Qt::SolidPattern));
  30. painter.drawEllipse(100, 50, 150, 150);
  31. } else if(ui->radioButton_green->isChecked()){
  32. // Якщо зелений, то отрісовиваємих зелений круг
  33. painter.setBrush(QBrush(Qt::green, Qt::SolidPattern));
  34. painter.drawEllipse(100, 50, 150, 150);
  35. } else if(ui->radioButton_blue->isChecked()){
  36. // Якщо синій, то отрісовиваємих синій круг
  37. painter.setBrush(QBrush(Qt::blue, Qt::SolidPattern));
  38. painter.drawEllipse(100, 50, 150, 150);
  39. } else {
  40. // Якщо нічого не вибрано, то отрісовиваємих білий круг
  41. painter.setBrush(QBrush(Qt::white, Qt::SolidPattern));
  42. painter.drawEllipse(100, 50, 150, 150);
  43. }
  44. }
  45.  
  46. /* Як тільки один з радіобаттон виявляється натискує, викликаємо перемальовування вмісту віджета, з яким працюємо. */
  47. void Widget::on_radioButton_red_clicked()
  48. {
  49. repaint();
  50. }
  51.  
  52. void Widget::on_radioButton_green_clicked()
  53. {
  54. repaint();
  55. }
  56.  
  57. void Widget::on_radioButton_blue_clicked()
  58. {
  59. repaint();
  60. }

Результат

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

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

Вам це подобається? Поділіться в соціальних мережах!

И
  • 22 березня 2017 р. 22:12

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

И
  • 22 березня 2017 р. 22:19

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

Evgenii Legotckoi
  • 22 березня 2017 р. 23:02

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

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

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

И
  • 23 березня 2017 р. 01:53

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

Evgenii Legotckoi
  • 23 березня 2017 р. 09:35

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

И
  • 23 березня 2017 р. 13:16

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

И
  • 23 березня 2017 р. 15:03

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

Evgenii Legotckoi
  • 23 березня 2017 р. 16:13

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

Evgenii Legotckoi
  • 23 березня 2017 р. 16:15

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

И
  • 23 березня 2017 р. 19:33

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

И
  • 24 березня 2017 р. 11:25

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

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
  • Останні коментарі
  • Evgenii Legotckoi
    16 квітня 2025 р. 17:08
    Благодарю за отзыв. И вам желаю всяческих успехов!
  • IscanderChe
    12 квітня 2025 р. 17:12
    Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
  • AK
    01 квітня 2025 р. 11:41
    Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
  • Evgenii Legotckoi
    09 березня 2025 р. 21:02
    К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
  • VP
    09 березня 2025 р. 16:14
    Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…