БлогNot. QT: простой обмен сигналами между двумя классами

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 [7160 просмотров]


теги: c++ программирование учебное qt

К этой статье пока нет комментариев, Ваш будет первым