У фреймворку 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
Доброго времени суток. Подскажите, пожалуйста, следующую вещь: что такое 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 файлов, что гораздо удобнее, чем смотреть в код и не понимать, к какому всё-таки окну это относится.
У программы нас не имеют статических окошек, как таковых - окна могут быть совершенно различными в зависимости от множества условий, и, "лепятся", прямо, на лету, при запуске. Те, кто начинал проекты, выбрали чистый код, и, тем кто с ними работает сейчас, приходится делать все без использования ui, либо, все переписывать, а, это не на один год работы - проекты большие,ведутся лет 20, множество модулей написаны на всем, что можно только себе вообразить, начиная от ассемблера(работаем с железом и драйверами, в том числе) и заканчивая C#, и, все это завязано на кроссплатформенный qt, поскольку, поддерживается и Линупс. Старая команда отвалила, набрали новыю... Переписывать все жестоко, да, и, опыта у меня маловато
Увидел, еще, один интересный момент. Вы написали про редактирование слота clicked(), а, в дизайнере я этой возможности не нашел, но, тут такой момент... у меня qt собрана самостоятельно, без creator-a, есть, только, дизайнер. А, в дизайнере нет поддержки слотов(по правой клавише мыши). Потом, поставил Creator, а, там, дизайнер открывается в контексте проекта, вот, там создание слота clicked,уже есть... Про этот момент я не знал, поэтому, и, не нашел в дизайнере, как создать слот... В новых версиях qt создание слотов из дизайнера вынесли...
Но согласитесь, что отсутствие ui - это проблема того, что проекты давно развиваются, имеется много легаси кода и того, что на момента развития проектов и сам Qt не был так сильно развит. Например, Qt4 и Qt5 довольно сильно различаются, да даже Qt 5.6 очень отличается от Qt 5.8 по некоторым модулям, особенно если полезть в сторону QML. А после пары калымов я вовсе зарёкся браться за проекты с Qt4, особенно те, которые пишутся на устаревших версиях VS. Наверняка, многое можно стандартизировать и шаблонизировать. В нашем проекте сотни диалоговых окон с ui, но все они создаются и наполняются динамически. А также имеют всего несколько базовых классов. Просто различные вкладки интерфейса скрываются или добавляются в зависимости от этих самых условий, про которые вы сказали. Ну а так да. - Переписывать всё действительно жёстко, если проекты давно развиваются, но это уже немного другая история.
Думаю, что это вполне логичное развитие продукта. Без Креатора - это бесполезный функционал.
Это логично. Просто, именно, это ввело меня в ступор и заставило отписать в комментариях вчера. Причем, в дизайнере(который отдельно, открывается, без creator-a) есть редактор сигналов и слотов, но, он пуст. А, Creator-a у меня на тот момент не стояло
Соглашусь,там люди начинали с делфи,вообще,в свое время,когда все зарождалось потом,постепенно,постепенно,все облагораживалось,портировалось на более вменяемые средства разработки... Наши ребята-программисты(среди которых и я пятый помощник десятого стажера),говорят,что,ui вполне можно было использовать... у нас,еще,осложняется все тем,что,мы поддерживаем sdk,свои,на которой заказчики строят ПО,этих sdk несколько,если переписать,то,будет,еще на sdk больше,поскольку,старую никуда не денешь,а,заказчики консервативны.Сделали один раз и навсегда... у нас сфера промышленных систем,там еще компы на DOS,встречаются,до сих пор!!!)))))))