QT: простой обмен сигналами между двумя классами
Всё основное о сигналах и слотах в QT сказано в этой заметке, и там же приведён пример приложения. Этот пример, наверное, ещё проще и возник как ответ на вопрос о том, как организовать обмен сигналами между виджетом и неким объектом, представленным отдельным классом.
Создадим виджет с формой на основе класса QWidget
действуя так же, как в этой статье.
Затем добавим в проект класс MyObject
, являющийся потомком базового класса Object
.
Для этого нажмём правую кнопку мыши на выделенном жирным шрифтом имени проекта, выберем пункт меню Добавить новый..., затем слева укажем язык C++, справа - пункт списка C++ Class, нажмём кнопку Выбрать..., в новом окне введём имя класса MyObject
и выберем из списка базовый класс QObject
.
Осталось нажать Далее и Завершить, пустой класс, готовый отправлять и принимать сигналы, создан.
Предусмотрим отправку из виджета сигнала некоторому объекту (другому классу) и слот для приёма информации от объекта.
Для этого изменим файл widget.h
следующим образом:
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include "myobject.h" //заголовочный файл класс объекта namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private: Ui::Widget *ui; MyObject Object; //Объект, с которым будем работать signals: void send_to_object(bool); //будем отправлять величину типа bool private slots: void get_from_object(bool); //и принимать такую же }; #endif // WIDGET_H
Суть механизма сигналов и слотов состоит в том, что виджет может использовать интерфейс сигналов и слотов других виджетов, не вникая в детали их реализации, не заботясь об очередности обработки сигналов и даже "не зная", будет ли сигнал обработан.
Объект просто посылает "внешнему миру" сигнал о том, что его состояние изменилось и другие объекты могут это учесть.
Заставим наш виджет посылать сигнал классу MyObject
, а последнему укажем принимать его в ещё не написанный слот get_from_gui
.
Осуществим и обратную связь. Виджет будет принимать в слот get_from_object
сигнал send_to_gui
, отправленный из объекта Object
.
Соединять сигналы со слотами можно в любой точке приложения, для удобства сделаем это в конструкторе виджета, изменив файл widget.cpp
следующим образом:
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); connect(this,SIGNAL(send_to_object(bool)),&Object,SLOT(get_from_gui(bool))); //Соединение 1 - от виджета к объекту connect(&Object,SIGNAL(send_to_gui(bool)),this,SLOT(get_from_object(bool))); //Соединение 2 - от объекта к виджету } Widget::~Widget() { delete ui; }
Ниже этого кода обеспечим реализацию слота виджета.
Чтобы отображать величину типа bool
, полученную от объекта, откроем двойным щелчком форму widget.ui
и перетащим на неё однострочное тектовое поле lineEdit
. Также добавим стандартный переключатель checkBox
.
форма виджета
Горячей клавишей Ctrl+W закроем форму и подтвердим её сохранение.
Теперь можно добавить в widget.cpp
слот, который будет менять текст, выведенный в lineEdit
в зависимости от того, истинная или ложная величина ему передана.
void Widget::get_from_object(bool value) { ui->lineEdit->setText(value==true?tr("true"):tr("false")); }
Перейдём к написанию класса объекта. В файле myobject.h
опишем сигнал и слот объекта, а также предусмотрим вектор из величин типа bool
, хранящий последовательность состояний объекта.
#ifndef MYOBJECT_H #define MYOBJECT_H #include <QObject> #include <QVector> class MyObject : public QObject { Q_OBJECT public: explicit MyObject(QObject *parent = 0); signals: void send_to_gui(bool); private slots: void get_from_gui(bool); private: //данные класса QVector <bool> state; }; #endif // MYOBJECT_H
В файле myobject.cpp
достаточно будет реализовать код слота.
void MyObject::get_from_gui(bool value) { state->append(value); //запомнить новое состояние emit send_to_gui(value); //и отправить виджету сигнал }
Виджет тоже должен когда-то отправлять сигнал, пусть это будет происходить при изменении состояния чекбокса. Когда оно меняется, чекбокс отправляет встроенный в него сигнал clicked()
Дважды щёлкнем по форме widget.ui
, затем нажмём правую кнопку на чекбоксе, щёлкнем пункт меню Перейти к слоту..., выберем из списка clicked()
и нажмём ОК.
создание слота в режиме дизайна формы
В widget.cpp
добавился ещё один слот, запрограммируем его:
void Widget::on_checkBox_clicked() { emit send_to_object(ui->checkBox->isChecked()); }
Объекту отправляется сигнал о текущем состоянии чекбокса, которое он заносит в свой список state
.
Теперь виджет работает и обменивается сигналами с объектом.
Скачать этот проект QT5 в архиве .zip, папка проекта уже создана внутри архива (3 Кб)
03.03.2018, 10:07 [7576 просмотров]