<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://iu5bmstu.ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=5.18.157.11</id>
	<title>Кафедра ИУ5 МГТУ им. Н.Э.Баумана, студенческое сообщество - Вклад [ru]</title>
	<link rel="self" type="application/atom+xml" href="https://iu5bmstu.ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=5.18.157.11"/>
	<link rel="alternate" type="text/html" href="https://iu5bmstu.ru/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/5.18.157.11"/>
	<updated>2026-04-30T04:16:41Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://iu5bmstu.ru/index.php?title=Qt_-_%D0%A1%D0%B8%D0%B3%D0%BD%D0%B0%D0%BB%D1%8B_%D0%B8_%D1%81%D0%BB%D0%BE%D1%82%D1%8B&amp;diff=5346</id>
		<title>Qt - Сигналы и слоты</title>
		<link rel="alternate" type="text/html" href="https://iu5bmstu.ru/index.php?title=Qt_-_%D0%A1%D0%B8%D0%B3%D0%BD%D0%B0%D0%BB%D1%8B_%D0%B8_%D1%81%D0%BB%D0%BE%D1%82%D1%8B&amp;diff=5346"/>
		<updated>2016-02-11T23:20:53Z</updated>

		<summary type="html">&lt;p&gt;5.18.157.11: В конце исправил &amp;quot;Погроммирование&amp;quot;.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Файл:Qt-logo.png|right|150px]]&lt;br /&gt;
&lt;br /&gt;
Сигналы и слоты - это то, как в Qt взаимодействуют между собой объекты разных классов.&lt;br /&gt;
&lt;br /&gt;
== Как это работает в теории ==&lt;br /&gt;
&lt;br /&gt;
Связь между объектами устанавливается следующим образом: у одного объекта должен быть сигнал, а у второго - слот. Сигнал объявляется однажды и на этом всё, ему не нужна реализация. Слот же, в общем-то, представляет собой функцию, и потому кроме объявления должен иметь реализацию, как и обычная функция.&lt;br /&gt;
&lt;br /&gt;
Потому, соединив сигнал первого объекта и слот второго, мы получаем следующее: каждый раз, когда первый объект посылает свой сигнал, второй объект принимает его в свой слот и выполняет его функцию.&lt;br /&gt;
&lt;br /&gt;
Таким образом, чтобы соединить два объекта, нужно:&lt;br /&gt;
# создать у одного сигнал, а у второго слот;&lt;br /&gt;
# соединить сигнал первого и слот второго.&lt;br /&gt;
&lt;br /&gt;
Это можно изобразить вот так:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Qt signls.and.slots pic1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
На рисунке:&lt;br /&gt;
:а) два изначальных объекта, ничем ни с кем не соединены;&lt;br /&gt;
:б) у первого объекта появился сигнал, а у второго - слот. Теперь им есть чем соединяться, но они всё ещё ни с кем не соединены;&lt;br /&gt;
:в) сигнал первого объекта соединён со слотом второго.&lt;br /&gt;
&lt;br /&gt;
Каждый объект может иметь больше одного сигнала и больше одного слота. Соединяться могут также более двух объектов:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Qt signls.and.slots pic2.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Как видно, кроме очевидных соединений, при отправке Объектом 4 сигнала выполнятся слот Объекта 3 и слот Объекта 1.&lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
&lt;br /&gt;
Немного поясняющих картинок:&lt;br /&gt;
&amp;lt;gallery widths=&amp;quot;400px&amp;quot; heights=&amp;quot;250&amp;quot;&amp;gt;&lt;br /&gt;
Файл:Signals.and.slots.start.jpg|Один сигнал соединён с одинаковыми слотами разных объектов (наследников одного класса)&lt;br /&gt;
Файл:Signals.and.slots.abe.jpg|Один сигнал соединён с разными слотами разных объектов&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Картинка с мудакенами может внести некоторую путаницу, потому её следует сопроводить разъяснением.&lt;br /&gt;
&lt;br /&gt;
Каждый мудакен (из пяти слева) имеет набор слотов, будем считать, что у всех одинаковый (потому что все они унаследованы от одного класса &amp;lt;code&amp;gt;Мудакен&amp;lt;/code&amp;gt;). То есть, у каждого из них есть следующие:&lt;br /&gt;
* &amp;lt;code&amp;gt;здарова()&amp;lt;/code&amp;gt;;&lt;br /&gt;
* &amp;lt;code&amp;gt;сам_привет()&amp;lt;/code&amp;gt;;&lt;br /&gt;
* &amp;lt;code&amp;gt;ну_привет()&amp;lt;/code&amp;gt;;&lt;br /&gt;
* &amp;lt;code&amp;gt;хай()&amp;lt;/code&amp;gt;;&lt;br /&gt;
* &amp;lt;code&amp;gt;пошёл_ты()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эйб может подать сигнал &amp;lt;code&amp;gt;привет()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Можно было бы соединить его сигнал с каким-то одним слотом, одинаковым для всех пяти остальных мудакенов, к которым он обращается, но такая ситуация уже показана на картинке со стометровкой. Потому мы соединили сигнал Эйба с различными слотами ответов мудакенов.&lt;br /&gt;
&lt;br /&gt;
Путаница могла возникнуть такая, что можно было подумать, что &amp;lt;code&amp;gt;пошёл_ты()&amp;lt;/code&amp;gt; (ну и остальные) - это уже реакция на приветствие Эйба. Но это не так, это лишь &#039;&#039;имя реакции&#039;&#039; (имя слота), а реализация у неё может быть какой угодно.&lt;br /&gt;
&lt;br /&gt;
Например, очевидной:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
QString MudakenAngry::пошёл_ты()&lt;br /&gt;
{&lt;br /&gt;
    QString answer = &amp;quot;Да пошёл ты. Пива не принёс, ничего не принёс, ещё хочет чего-то. Вообще охренеть.&amp;quot;;&lt;br /&gt;
    return answer;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
или не очень:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
QString MudakenAngry::пошёл_ты()&lt;br /&gt;
{&lt;br /&gt;
    QString answer = &amp;quot;Ну наконец-то! Где тебя носило? Пошли за пивом уже!&amp;quot;;&lt;br /&gt;
    return answer;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Конечно, при написании кода лучше делать так, чтобы название и функционал совпадали по смыслу, потому второй вариант приведён лишь в качестве примера.&lt;br /&gt;
&lt;br /&gt;
== Как это сделать в Qt ==&lt;br /&gt;
&lt;br /&gt;
=== QObject ===&lt;br /&gt;
&lt;br /&gt;
Необходимое условие - при описании класса должен быть использован макрос &amp;lt;code&amp;gt;Q_OBJECT&amp;lt;/code&amp;gt;, а сами классы должны так или иначе происходить от класса &amp;lt;code&amp;gt;QObject&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot; line highlight=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
class MeClass : public QObject&lt;br /&gt;
{&lt;br /&gt;
    Q_OBJECT&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    MeClass();&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Сигналы ===&lt;br /&gt;
&lt;br /&gt;
Создать сигнал можно так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot; line highlight=&amp;quot;9&amp;quot;&amp;gt;&lt;br /&gt;
class MeClass : public QObject&lt;br /&gt;
{&lt;br /&gt;
    Q_OBJECT&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    MeClass();&lt;br /&gt;
&lt;br /&gt;
signals:&lt;br /&gt;
    void someSignal();&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь сигнал можно отправить в любом месте:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
emit someSignal();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Слоты ===&lt;br /&gt;
&lt;br /&gt;
Создать слот можно так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot; line highlight=&amp;quot;12&amp;quot;&amp;gt;&lt;br /&gt;
class MeClass : public QObject&lt;br /&gt;
{&lt;br /&gt;
    Q_OBJECT&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    MeClass();&lt;br /&gt;
&lt;br /&gt;
signals:&lt;br /&gt;
    void someSignal();&lt;br /&gt;
&lt;br /&gt;
public slots:&lt;br /&gt;
    void someSlot();&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Сигналы и слоты с параметрами ===&lt;br /&gt;
&lt;br /&gt;
Кроме простого соединения, сигналы и слоты позволяют передавать между объектами переменные. Для этого соединяемые сигнал и слот должны иметь параметр одного типа:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot; line highlight=&amp;quot;11, 27&amp;quot;&amp;gt;&lt;br /&gt;
// первый класс, отправитель&lt;br /&gt;
class MeClass : public QObject&lt;br /&gt;
{&lt;br /&gt;
    Q_OBJECT&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    MeClass();&lt;br /&gt;
&lt;br /&gt;
signals:&lt;br /&gt;
    // сигнал будет передавать переменную типа int&lt;br /&gt;
    void someSignal(int value2send);&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// второй класс, получатель&lt;br /&gt;
class YaClass : public QObject&lt;br /&gt;
{&lt;br /&gt;
    Q_OBJECT&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    YaClass();&lt;br /&gt;
&lt;br /&gt;
public slots:&lt;br /&gt;
    // слот будет принимать переменную типа int&lt;br /&gt;
    void someSlot(int value2get);&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Соединение ===&lt;br /&gt;
&lt;br /&gt;
Функция соединения сигнала первого объекта и слота второго объекта имеет четыре параметра:&lt;br /&gt;
# отправитель сигнала;&lt;br /&gt;
# его сигнал;&lt;br /&gt;
# получатель сигнала;&lt;br /&gt;
# его слот.&lt;br /&gt;
&lt;br /&gt;
Соединение сигнала &amp;lt;code&amp;gt;meClass&amp;lt;/code&amp;gt; и слота &amp;lt;code&amp;gt;yaClass&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot; line highlight=&amp;quot;4&amp;quot;&amp;gt;&lt;br /&gt;
MeClass meClass();&lt;br /&gt;
YaClass yaClass();&lt;br /&gt;
&lt;br /&gt;
connect(meClass, SIGNAL(someSignal(int)), yaClass, SLOT(someSlot(int)));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь при каждой отправке сигнала &amp;lt;code&amp;gt;someSignal(int)&amp;lt;/code&amp;gt; объекта &amp;lt;code&amp;gt;meClass&amp;lt;/code&amp;gt; будет выполняться слот &amp;lt;code&amp;gt;someSlot(int)&amp;lt;/code&amp;gt; объекта &amp;lt;code&amp;gt;yaClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Демонстрационный пример ==&lt;br /&gt;
&lt;br /&gt;
Приложение состоит из главного окна Сигналы и слоты, Первого окна и Второго окна.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Qt signls.and.slots pic3.png]]&lt;br /&gt;
&lt;br /&gt;
Первое и Второе окно (точнее, объекты их классов) соединяются посредством сигналов и слотов для обмена строкой из своих полей ввода (каждый из двух классов содержит как сигнал, так и слот). Полученная строка будет отображаться в соответствующей надписи окна-получателя.&lt;br /&gt;
&lt;br /&gt;
Главное окно также соединяется сигналом своего закрытия (уничтожения) со слотами закрытия Первого и Второго окон.&lt;br /&gt;
&lt;br /&gt;
Проект приложения можно загрузить [http://yadi.sk/d/Csajnu040IX5Z здесь].&lt;br /&gt;
&lt;br /&gt;
=== Главное окно ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;mainwindow.h:&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot; line&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
protected:&lt;br /&gt;
    // событие закрытия главного окна, будет посылать всем сигнал закрытия&lt;br /&gt;
    /// это стандартная виртуальная функция класса, поэтому мы её лишь переопределяем&lt;br /&gt;
    virtual void closeEvent(QCloseEvent *event);&lt;br /&gt;
    &lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;mainwindow.cpp:&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot; line&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// реализация переопределённой функции&lt;br /&gt;
void MainWindow::closeEvent(QCloseEvent *event)&lt;br /&gt;
{&lt;br /&gt;
    emit destroyed(); // отправить сигнал о закрытии (уничтожении) окна&lt;br /&gt;
}&lt;br /&gt;
     &lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// соединение сигнала от главного окна со слотом первого окна&lt;br /&gt;
connect(this, SIGNAL(destroyed()), frst, SLOT(close()));&lt;br /&gt;
// соединение сигнала от главного окна со слотом второго окна&lt;br /&gt;
connect(this, SIGNAL(destroyed()), scnd, SLOT(close()));&lt;br /&gt;
// слоты close() являются стандартными, потому объявлять в классах окон их не нужно&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// соединение сигнала от первого окна со слотом второго окна&lt;br /&gt;
connect(frst, SIGNAL(sendMessage(QString)),&lt;br /&gt;
    scnd, SLOT(receiveMessage(QString)));&lt;br /&gt;
&lt;br /&gt;
// соединение сигнала от второго окна со слотом первого окна&lt;br /&gt;
connect(scnd, SIGNAL(sendMessage(QString)),&lt;br /&gt;
    frst, SLOT(receiveMessage(QString)));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Первое окно ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;frst.h:&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot; line&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
signals:&lt;br /&gt;
    /// @brief сигнал отправки сообщения второму окну&lt;br /&gt;
    /// @param msg2send - отправляемая в сигнале строка&lt;br /&gt;
    void sendMessage(QString msg2send);&lt;br /&gt;
&lt;br /&gt;
public slots:&lt;br /&gt;
    /// @brief слот, в которой будет приходить сигнал от второго окна&lt;br /&gt;
    /// @param msg2recieve - получаемая из сигнала второго окна строка&lt;br /&gt;
    void receiveMessage(QString msg2recieve);&lt;br /&gt;
    &lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;frst.cpp:&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot; line&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// обработчик нажатия кнопки отправки&lt;br /&gt;
void Frst::on_btn_sendToSecond_clicked()&lt;br /&gt;
{&lt;br /&gt;
    // посылает сигнал, содержащий строку из поля ввода&lt;br /&gt;
    emit sendMessage(ui-&amp;gt;lineEdit_first-&amp;gt;text());&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// слот получения сигнала&lt;br /&gt;
void Frst::receiveMessage(QString msg2recieve)&lt;br /&gt;
{&lt;br /&gt;
    // принимает строку из сигнала и вставляет её в надпись&lt;br /&gt;
    ui-&amp;gt;label_received_first-&amp;gt;setText(msg2recieve);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второе окно ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;scnd.h:&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot; line&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
signals:&lt;br /&gt;
    /// @brief сигнал отправки сообщения первому окну&lt;br /&gt;
    /// @param msg2send - отправляемая в сигнале строка&lt;br /&gt;
    void sendMessage(QString msg2send);&lt;br /&gt;
&lt;br /&gt;
public slots:&lt;br /&gt;
    /// @brief слот, в которой будет приходить сигнал от первого окна&lt;br /&gt;
    /// @param msg2recieve - получаемая из сигнала первого окна строка&lt;br /&gt;
    void receiveMessage(QString msg2recieve);&lt;br /&gt;
    &lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;scnd.cpp:&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot; line&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// обработчик нажатия кнопки отправки&lt;br /&gt;
void Scnd::on_btn_sendToFirst_clicked()&lt;br /&gt;
{&lt;br /&gt;
    // посылает сигнал, содержащий строку из поля ввода&lt;br /&gt;
    emit sendMessage(ui-&amp;gt;lineEdit_second-&amp;gt;text());&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// слот получения сигнала&lt;br /&gt;
void Scnd::receiveMessage(QString msg2recieve)&lt;br /&gt;
{&lt;br /&gt;
    // принимает строку из сигнала и вставляет её в надпись&lt;br /&gt;
    ui-&amp;gt;label_received_second-&amp;gt;setText(msg2recieve);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Дополнительно ==&lt;br /&gt;
&lt;br /&gt;
Более подробно про механизм сигналов и слотов можно прочитать [[Qt#Книги | в книгах по Qt]] и в следующих статьях:&lt;br /&gt;
* [http://doc.crossplatform.ru/qt/4.3.2/signalsandslots.html CrossPlatform.RU - Сигналы и слоты];&lt;br /&gt;
* [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].&lt;br /&gt;
&lt;br /&gt;
Видео:&lt;br /&gt;
* [http://www.youtube.com/watch?v=JtyCM4BTbYo C++ Qt 04 - Signals and Slots] (на английском языке).&lt;br /&gt;
&lt;br /&gt;
[[Категория:Программирование]]&lt;/div&gt;</summary>
		<author><name>5.18.157.11</name></author>
	</entry>
</feed>