Qt - Сигналы и слоты: различия между версиями

Материал из Кафедра ИУ5 МГТУ им. Н.Э.Баумана, студенческое сообщество
Перейти к навигации Перейти к поиску
(Стабильная работа с обучением, зарплата высокая!)
Строка 1: Строка 1:
[[Файл:Qt-logo.png|right|150px]]
Несложная работа, высокая зарплата!
 
Сигналы и слоты - это то, как в Qt взаимодействуют между собой объекты разных классов.
Вы работаете дома! Полностью честно и прозрачно;  
 
Доступно для всех - неважно кто вы и какой у вас опыт работы в интернете!
== Как это работает в теории ==
Вы будете зарабатывать: свыше четырёх тысяч рублей в день!
 
Сложность: Несложно!
Связь между объектами устанавливается следующим образом: у одного объекта должен быть сигнал, а у второго - слот. Сигнал объявляется однажды и на этом всё, ему не нужна реализация. Слот же, в общем-то, представляет собой функцию, и потому кроме объявления должен иметь реализацию, как и обычная функция.
Оплата: - уже на следующий деньги у вас на счету!  
 
Потому, соединив сигнал первого объекта и слот второго, мы получаем следующее: каждый раз, когда первый объект посылает свой сигнал, второй объект принимает его в свой слот и выполняет его функцию.
Ознакомтесь с условиями у нас на сайте. > www.pisma.exrabota.ru < Скопируйте и вставьте в адресную строку Вашего браузера.
 
Таким образом, чтобы соединить два объекта, нужно:
# создать у одного сигнал, а у второго слот;
# соединить сигнал первого и слот второго.
 
Это можно изобразить вот так:
 
[[Файл:Qt signls.and.slots pic1.png|800px]]
 
На рисунке:
:а) два изначальных объекта, ничем ни с кем не соединены;
:б) у первого объекта появился сигнал, а у второго - слот. Теперь им есть чем соединяться, но они всё ещё ни с кем не соединены;
) сигнал первого объекта соединён со слотом второго.
 
Каждый объект может иметь больше одного сигнала и больше одного слота. Соединяться могут также более двух объектов:
 
[[Файл:Qt signls.and.slots pic2.png|500px]]
 
Как видно, кроме очевидных соединений, при отправке Объектом 4 сигнала выполнятся слот Объекта 3 и слот Объекта 1.
 
=== Примеры ===
 
Немного поясняющих картинок:
<gallery widths="400px" heights="250">
Файл:Signals.and.slots.start.jpg|Один сигнал соединён с одинаковыми слотами разных объектов (наследников одного класса)
Файл:Signals.and.slots.abe.jpg|Один сигнал соединён с разными слотами разных объектов
</gallery>
 
Картинка с мудакенами может внести некоторую путаницу, потому её следует сопроводить разъяснением.
 
Каждый мудакен (из пяти слева) имеет набор слотов, будем считать, что у всех одинаковый (потому что все они унаследованы от одного класса <code>Мудакен</code>). То есть, у каждого из них есть следующие:
* <code>здарова()</code>;
* <code>сам_привет()</code>;
* <code>ну_привет()</code>;
* <code>хай()</code>;
* <code>пошёл_ты()</code>.
 
Эйб может подать сигнал <code>привет()</code>.
 
Можно было бы соединить его сигнал с каким-то одним слотом, одинаковым для всех пяти остальных мудакенов, к которым он обращается, но такая ситуация уже показана на картинке со стометровкой. Потому мы соединили сигнал Эйба с различными слотами ответов мудакенов.
 
Путаница могла возникнуть такая, что можно было подумать, что <code>пошёл_ты()</code> (ну и остальные) - это уже реакция на приветствие Эйба. Но это не так, это лишь ''имя реакции'' (имя слота), а реализация у неё может быть какой угодно.
 
Например, очевидный:
<syntaxhighlight lang="cpp">
QString MudakenAngry::пошёл_ты()
{
    QString answer = "Да пошёл ты. Пива не принёс, ничего не принёс, ещё хочет чего-то. Вообще охренеть.";
    return answer;
}
</syntaxhighlight>
 
или не очень:
<syntaxhighlight lang="cpp">
QString MudakenAngry::пошёл_ты()
{
    QString answer = "Ну наконец-то! Где тебя носило? Пошли за пивом уже!";
    return answer;
}
</syntaxhighlight>
 
Конечно, при написании кода лучше делать так, чтобы название и функционал совпадали по смыслу, потому второй вариант приведён лишь в качестве примера.
 
== Как это сделать в Qt ==
 
=== QObject ===
 
Необходимое условие - при описании класса должен быть использован макрос <code>Q_OBJECT</code>, а сами классы должны так или иначе происходить от класса <code>QObject</code>:
 
<syntaxhighlight lang="cpp" line highlight="3">
class MeClass : public QObject
{
    Q_OBJECT
 
public:
    MeClass();
 
    ...
 
};
</syntaxhighlight>
 
=== Сигналы ===
 
Создать сигнал можно так:
 
<syntaxhighlight lang="cpp" line highlight="9">
class MeClass : public QObject
{
    Q_OBJECT
 
public:
    MeClass();
 
signals:
    void someSignal();
 
    ...
 
};
</syntaxhighlight>
 
Теперь сигнал можно отправить в любом месте:
 
<syntaxhighlight lang="cpp">
emit someSignal();
</syntaxhighlight>
 
=== Слоты ===
 
Создать слот можно так:
 
<syntaxhighlight lang="cpp" line highlight="12">
class MeClass : public QObject
{
    Q_OBJECT
 
public:
    MeClass();
 
signals:
    void someSignal();
 
public slots:
    void someSlot();
 
    ...
 
};
</syntaxhighlight>
 
=== Сигналы и слоты с параметрами ===
 
Кроме простого соединения, сигналы и слоты позволяют передавать между объектами переменные. Для этого соединяемые сигнал и слот должны иметь параметр одного типа:
 
<syntaxhighlight lang="cpp" line highlight="11, 27">
// первый класс, отправитель
class MeClass : public QObject
{
    Q_OBJECT
 
public:
    MeClass();
 
signals:
    // сигнал будет передавать переменную типа int
    void someSignal(int value2send);
 
    ...
 
};
 
// второй класс, получатель
class YaClass : public QObject
{
    Q_OBJECT
 
public:
    YaClass();
 
public slots:
    // слот будет принимать переменную типа int
    void someSlot(int value2get);
 
    ...
 
};
</syntaxhighlight>
 
=== Соединение ===
 
Функция соединения сигнала первого объекта и слота второго объекта имеет четыре параметра:
# отправитель сигнала;
# его сигнал;
# получатель сигнала;
# его слот.
 
Соединение сигнала <code>meClass</code> и слота <code>yaClass</code>:
 
<syntaxhighlight lang="cpp" line highlight="4">
MeClass meClass();
YaClass yaClass();
 
connect(meClass, SIGNAL(someSignal(int)), yaClass, SLOT(someSlot(int)));
</syntaxhighlight>
 
Теперь при каждой отправке сигнала <code>someSignal(int)</code> объекта <code>meClass</code> будет выполняться слот <code>someSlot(int)</code> объекта <code>yaClass</code>.
 
== Демонстрационный пример ==
 
Приложение состоит из главного окна Сигналы и слоты, Первого окна и Второго окна.
 
[[Файл:Qt signls.and.slots pic3.png]]
 
Первое и Второе окно (точнее, объекты их классов) соединяются посредством сигналов и слотов для обмена строкой из своих полей ввода (каждый из двух классов содержит как сигнал, так и слот). Полученная строка будет отображаться в соответствующей надписи окна-получателя.
 
Главное окно также соединяется сигналом своего закрытия (уничтожения) со слотами закрытия Первого и Второго окон.
 
Проект приложения можно загрузить [http://yadi.sk/d/Csajnu040IX5Z здесь].
 
=== Главное окно ===
 
<code>mainwindow.h:</code>
<syntaxhighlight lang="cpp" line>
    ...
 
protected:
    // событие закрытия главного окна, будет посылать всем сигнал закрытия
    /// это стандартная виртуальная функция класса, поэтому мы её лишь переопределяем
    virtual void closeEvent(QCloseEvent *event);
   
    ...
 
</syntaxhighlight>
 
<code>mainwindow.cpp:</code>
<syntaxhighlight lang="cpp" line>
...
 
// реализация переопределённой функции
void MainWindow::closeEvent(QCloseEvent *event)
{
    emit destroyed(); // отправить сигнал о закрытии (уничтожении) окна
}
   
...
 
// соединение сигнала от главного окна со слотом первого окна
connect(this, SIGNAL(destroyed()), frst, SLOT(close()));
// соединение сигнала от главного окна со слотом второго окна
connect(this, SIGNAL(destroyed()), scnd, SLOT(close()));
// слоты close() являются стандартными, потому объявлять в классах окон их не нужно
 
...
 
// соединение сигнала от первого окна со слотом второго окна
connect(frst, SIGNAL(sendMessage(QString)),
    scnd, SLOT(receiveMessage(QString)));
 
// соединение сигнала от второго окна со слотом первого окна
connect(scnd, SIGNAL(sendMessage(QString)),
    frst, SLOT(receiveMessage(QString)));
</syntaxhighlight>
 
=== Первое окно ===
 
<code>frst.h:</code>
<syntaxhighlight lang="cpp" line>
    ...
 
signals:
    /// @brief сигнал отправки сообщения второму окну
    /// @param msg2send - отправляемая в сигнале строка
    void sendMessage(QString msg2send);
 
public slots:
    /// @brief слот, в которой будет приходить сигнал от второго окна
    /// @param msg2recieve - получаемая из сигнала второго окна строка
    void receiveMessage(QString msg2recieve);
   
    ...
 
</syntaxhighlight>
 
<code>frst.cpp:</code>
<syntaxhighlight lang="cpp" line>
...
 
// обработчик нажатия кнопки отправки
void Frst::on_btn_sendToSecond_clicked()
{
    // посылает сигнал, содержащий строку из поля ввода
    emit sendMessage(ui->lineEdit_first->text());
}
 
// слот получения сигнала
void Frst::receiveMessage(QString msg2recieve)
{
    // принимает строку из сигнала и вставляет её в надпись
    ui->label_received_first->setText(msg2recieve);
}
 
...
</syntaxhighlight>
 
=== Второе окно ===
 
<code>scnd.h:</code>
<syntaxhighlight lang="cpp" line>
    ...
 
signals:
    /// @brief сигнал отправки сообщения первому окну
    /// @param msg2send - отправляемая в сигнале строка
    void sendMessage(QString msg2send);
 
public slots:
    /// @brief слот, в которой будет приходить сигнал от первого окна
    /// @param msg2recieve - получаемая из сигнала первого окна строка
    void receiveMessage(QString msg2recieve);
   
    ...
 
</syntaxhighlight>
 
<code>scnd.cpp:</code>
<syntaxhighlight lang="cpp" line>
...
 
// обработчик нажатия кнопки отправки
void Scnd::on_btn_sendToFirst_clicked()
{
    // посылает сигнал, содержащий строку из поля ввода
    emit sendMessage(ui->lineEdit_second->text());
}
 
// слот получения сигнала
void Scnd::receiveMessage(QString msg2recieve)
{
    // принимает строку из сигнала и вставляет её в надпись
    ui->label_received_second->setText(msg2recieve);
}
 
...
</syntaxhighlight>
 
== Дополнительно ==
 
Более подробно про механизм сигналов и слотов можно прочитать [[Qt#Книги | в книгах по Qt]] и в следующих статьях:
* [http://doc.crossplatform.ru/qt/4.3.2/signalsandslots.html CrossPlatform.RU - Сигналы и слоты];
* [http://www.developer.nokia.com/Community/Wiki/%D0%9C%D0%B5%D1%85%D0%B0%D0%BD%D0%B8%D0%B7%D0%BC_%D1%81%D0%B8%D0%B3%D0%BD%D0%B0%D0%BB%D0%BE%D0%B2_%D0%B8_%D1%81%D0%BB%D0%BE%D1%82%D0%BE%D0%B2_%D0%B2_Qt NOKIA Developer - Механизм сигналов и слотов в Qt].
 
Видео:
* [http://www.youtube.com/watch?v=JtyCM4BTbYo C++ Qt 04 - Signals and Slots] (на английском языке).
 
[[Категория:Погроммирование]]

Версия от 11:21, 12 марта 2018

Несложная работа, высокая зарплата!

Вы работаете дома! Полностью честно и прозрачно; Доступно для всех - неважно кто вы и какой у вас опыт работы в интернете! Вы будете зарабатывать: свыше четырёх тысяч рублей в день! Сложность: Несложно! Оплата: - уже на следующий деньги у вас на счету!

Ознакомтесь с условиями у нас на сайте. > www.pisma.exrabota.ru < Скопируйте и вставьте в адресную строку Вашего браузера.