Что такое сигналы и слоты? - PullRequest
18 голосов
/ 23 ноября 2008

Может кто-нибудь объяснить простыми словами шаблон "сигналы и слоты"?

Ответы [ 6 ]

23 голосов
/ 23 ноября 2008

Сигналы и слоты - это способ разъединения отправителя (сигнала) и нуля или более получателей (слотов). Допустим, у вас есть система, в которой есть события, которые вы хотите сделать доступными для любой другой части системы, заинтересованной в этих событиях. Вместо того, чтобы жестко связывать код, который генерирует событие, с кодом, который хочет знать об этих событиях, вы должны использовать шаблон сигналов и слотов.

Когда отправитель сигнализирует о событии (обычно вызывая функцию, связанную с этим событием / сигналом), все получатели для этого события автоматически вызываются. Это позволяет подключать и отключать приемники по мере необходимости в течение срока действия программы.

Поскольку этот вопрос был помечен как C ++, здесь есть ссылка на библиотеку Boost.Signals , в которой содержится гораздо более подробное объяснение.

13 голосов
/ 23 ноября 2008

Я думаю, что лучше всего описать сигналы и слоты, когда вы рассматриваете их как возможный инструмент реализации для Шаблон наблюдателя или Шаблон публикации / подписчика . На стороне издателя есть один signal, например buttonPressed(IdType). При каждом нажатии кнопки вызываются все слоты, подключенные к этому сигналу. Слоты на стороне подписчика. Слот может быть, например, sendMail(IdType).

Наряду с событием «кнопка нажата», слот будет знать, какая кнопка была нажата, так как идентификатор был бы передан. IdType представляет тип данных, передаваемых по соединению между издателем и подписчиком. Для Абонента возможна операция connect(signal, slot), которая может соединить buttonPressed(IdType) с sendMail(IdType), поэтому при нажатии кнопки вызывается именно этот слот.

Хорошая вещь об этом заключается в том, что абонент (сторона слота) не должен заботиться о деталях сигнала. Просто нужно подключиться. Таким образом, здесь мы имеем большое количество слабых связей 1015 *. Вы можете изменить реализацию кнопок, но интерфейс для слотов останется прежним.

Посмотрите на Сигналы / слоты Qt или Повышающие сигналы для получения дополнительной информации.

6 голосов
/ 23 ноября 2008

Представьте, что в вашем приложении есть графический интерфейс. В большинстве случаев поток управления не будет очень линейным, то есть вместо четкой последовательности действий у вас будет пользователь, взаимодействующий с GUI (например, кнопки, меню и т. Д.).

По сути, это модель, управляемая событиями, которая может быть реализована с помощью шаблона сигналов и слотов. сигналы - это события, которые генерируются объектами (например, компонентами GUI), а слоты являются приемниками этих событий.

Вот пример: представьте, что у вас есть флажок, представленный в виде объекта на вашем языке программирования. С этим флажком может произойти несколько вещей: он может быть переключен, что, в свою очередь, также означает, что он установлен или не установлен. Это сигналы, которые он может излучать. Мы назовем их checkboxToggled, checkboxSet и checkboxUnset. Как вы видите, в этом примере флажок всегда будет издавать сигнал checkboxToggled при переключении, но также точно один из двух других сигналов, в зависимости от того, как изменяется состояние.

Теперь представьте, что у вас есть некоторые другие объекты, а именно метка, которая в этом примере всегда существует как объект, но может «появляться» и «исчезать», и системный звуковой сигнал (также представленный объектом), который может звуковой сигнал. Это слоты, которые имеют эти объекты. Мы будем называть их «messageAppear», «messageDisappear» и «beep».

Предположим, вы хотите, чтобы системный звуковой сигнал издавал звуковой сигнал при каждом переключении флажка, а метка появлялась или исчезала в зависимости от того, установил ли пользователь флажок или снял его.

Таким образом, вы должны подключить следующие сигналы к следующим слотам (сигналы слева, слоты справа):

checkboxToggled -> beep
checkboxSet -> messageAppear
checkboxUnset -> messageDisappear

Вот и все.

сигналы и слоты также могут иметь аргументы. Например, используя ползунок, который устанавливает числовое значение, вы хотите отправить измененное значение вместе с излучаемым сигналом, как только пользователь переместит ползунок: sliderChanged (int).

Конечно, чтобы действительно сделать что-то полезное, вы бы написали несколько собственных классов, которые содержали бы некоторые собственные сигналы и слоты. Это делается довольно легко, и с помощью этих собственных сигналов и слотов у вас есть хороший способ взаимодействия с GUI или другими частями вашего кода управляемым событиями образом.

Имейте в виду, что сигналы и слоты часто симметричны в том смысле, что часто может быть сигнал, соответствующий слоту. Например, флажок может испускать сигнал при переключении, но он также может содержать слот, который переключает сам флажок. Было бы легко реализовать отдельные флажки, которые всегда установлены напротив друг друга.

4 голосов
/ 23 ноября 2008

Я предполагаю, что вы говорите о сигналах и слотах QT.
Это очень просто.

Экземпляр класса может запустить сигнал, а другой экземпляр, возможно, другого класса может перехватить этот сигнал в слоте. Это похоже на вызов функции только в том, что парню, который вызывает функцию, не нужно знать, кто хочет получить вызов.

Лучший способ проиллюстрировать это на примере.
Класс QPushButton имеет сигнал QPushButton :: clicked (). Этот сигнал срабатывает при каждом нажатии кнопки. Кнопка не должна знать, кому интересно знать, что произошел щелчок. он просто запускает сигнал, и тот, кто заинтересован, может подключиться к нему.
QDialog, в котором находится кнопка, не может не знать, когда была нажата кнопка. Он имеет слот MyDialog :: buttonClicked (). В MyDialog c'or необходимо подключить () сигнал нажатия кнопок () к слоту диалогового окна buttonClicked (), чтобы слот вызывался при срабатывании сигнала.

Куча более продвинутых вещей:

  • Аргументы, сигнал может иметь аргументы, и эти аргументы также могут передаваться в слот.
  • межпотоковые вызовы - если вы устанавливаете соединение через сигнальный слот, которое должно быть перекрестным, то QT автоматически буферизует сигналы и ставит их в очередь в нужный поток. Это происходит автоматически, например, когда поток графического интерфейса должен общаться с рабочим потоком.

Вот дополнительная информация в документации QT.

1 голос
/ 14 августа 2013

Лучший пример и объяснение, которое я нашел для сигналов и слотов, это эта статья проекта кода .

0 голосов
/ 07 мая 2017

Существует распространенное заблуждение, что классы являются существительными, такими как Человек, Собака, Велосипед и тому подобное. Тогда имеет смысл думать, что у человека (экземпляра) есть собака и велосипед.

Давайте начнем с того, что объекты (должны быть). Объекты - это данные и процедуры. Какие программы? Данные и процедуры. Предполагается, что объекты являются (относительно) «небольшими» независимыми подпрограммами. Так как программированию преподают очень расплывчато и неправильно (люди нуждаются в цитировании), люди думают, что все должно быть классом или объектом. Это не так, объекты - это «маленькие» независимые программы с «маленьким» API (открытые подпрограммы). Некоторые программисты даже не разбивают свой проект на подпрограммы и просто используют объекты, где данные и процедуры более подходят.

Теперь, предполагая, что мы согласны с тем, что объекты являются программами, мы можем согласиться с тем, что в большинстве случаев программам не нужно иметь копии других программ аналогичного размера и сложности (т. Е. Объект не имеет указателя на другой объект). ), для управления данными могут потребоваться небольшие программы (например, структуры данных), но imho не нужен другой объект.

Почему? Потому что связывание объектов делает их зависимыми. Почему это плохо? Потому что, когда объекты независимы, вы можете проверить их, а также пообещать другим программистам и клиентам, что объект (небольшая независимая программа) способен выполнять определенные задачи с высокой степенью достоверности. Вы также можете быть уверены, что он продолжает работать до тех пор, пока в этот объект не было внесено никаких изменений.

Так что же такое слоты и сигналы? Если вы понимаете, что объекты похожи на программы, и в идеале они не должны содержать копии или указатели на другие объекты, вам нужен какой-то способ для их связи. Например, процессы, которые запускаются на вашем компьютере, могут использовать сокеты, IP-адреса и порты для связи. Объекты могут использовать что-то очень похожее на RPC , называемое сигналами и слотами. Это структура данных, предназначенная в качестве посредника между двумя большими объектами, которые хранят подпрограммы объекта (slots) и позволяют другим объектам вызывать (signal) эти подпрограммы (slots) с подходящими параметрами, ничего не зная об этих других объекты, отличные от того, какие параметры им требуются.

Таким образом, базовой структурой являются наборы (возможно, массивы) (возможно) строго типизированных указателей процедур, которые другие объекты могут вызывать с подходящими параметрами без указателя на эти объекты. Вызывающим абонентам нужен только доступ к объекту сигнала (который не содержит подробностей реализации), который определяет ожидаемые параметры.

Это также гибко, поскольку допускает некоторые особые варианты использования, такие как слоты, которые реагируют на сигнал только один раз, несколько слотов для одного сигнала и другие подобные случаи использования, такие как дебасинг.

...