Qt лямбда функции connect

Опубликовано: 17.05.2024

Я экспериментировал с новыми слотами Lambda в Qt, и я не могу заставить его работать по какой-то причине. Вот соответствующие части кода, который терпит неудачу:

Я действительно застрял на этом.

Решение

ОБНОВИТЬ:
Это перегрузка QObject::connect вызов, на который вы пытаетесь сослаться, и что ваша ошибка говорит, что не может найти, основываясь на параметрах, которые вы ему даете:

У вас есть в параметрах:

Ваш QObject * отправитель не QSystemTrayIcon , это QAction * , Поэтому это недопустимый сигнал для подключения. Если вы хотите подключиться к сигналу активации QSystemTrayIcon Вы должны пройти QSystemTrayIcon указатель в качестве первого параметра.

Этот функтор выглядит так, как будто он может работать. Дважды проверьте примеры лямбды, если она не работает.

Это относится к новому лямбда-синтаксису, поддерживаемому в Qt 5, и если ваш компилятор поддерживает его.

Новое: подключение к простой функции

Новый синтаксис может даже соединяться с функциями, а не только с объектами QObject:

connect(sender, &Sender::valueChanged, someFunction);

профессионал

можно использовать с tr1::bind

может использоваться с лямбда-выражениями c ++ 11

connect(sender, &Sender::valueChanged,
tr1::bind(receiver, &Receiver::updateValue, "senderValue", tr1::placeholder::_1) );

connect(sender, &Sender::valueChanged, [=](const QString &newValue) <
receiver->updateValue("senderValue", newValue);
> );

минусы

Нет автоматического отключения, когда «приемник» уничтожен

На вики-странице приведено несколько примеров использования лямбда-функций:

И если вы проверяете MSDN, в синтаксисе Lambda довольно много:

Он становится немного сложным со всеми поддерживаемыми опциями c ++, возвращаемыми значениями, областью видимости переменных, ссылками на переменные и т. Д. Поэтому на данный момент поиск близкого примера должен работать.

Но, как было сказано в комментариях выше, вероятно, есть лучший способ сделать это.

Вместо того, чтобы создать экземпляр QAction как указатель внутри вашего основного виджета или QMainWindow и подключите его к слоту закрытия событий этого окна. Вот так:

Надеюсь, это поможет.

Другие решения

Настоящая проблема заключалась в том, что я пытался получить QSystemTrayIcon сигнал от QAction. Это будет работать:

Ключ в том, что вы используете &QAction :: срабатывает, не &QSystemTrayIcon :: активировано.

QSignalMapper является замечательным классом, чтобы организовать работу сигналов и слотов для динамически создаваемых объектов. Например, динамически создаваемых кнопок или объектов в QStackedWidget. Особенно это было актуально в устаревших версиях программного обеспечения, то есть базировавшегося на Qt 4.8 , где система сигналов и слотов строилась на применении макросов. Но в текущих реалиях новый синтаксис на указателях значительно более удобен, а также поддерживает лямбда функции, что может позволить и вовсе избавиться от применения QSignalMapper, который будет выглядеть как монструозный атавизм в новых проектах, которые используют последние версии фреймворка Qt и стандартов языка C++ .

А если учесть ещё и перегрузку map() и mapped() , то это делает код с QSignalMapper ещё более страшным, если использовать коннекты сигналов и слотов с использованием указателей, поскольку необходимо кастовать как сигналы, так и слоты, но об этом чуть позже.

Поэтому давайте рассмотрим небольшой проект, который будет основываться на примере из официальной документации Qt. А именно, пример будет следующий. У нас имеется QLabel, QPushButton и Vertical Layout . По нажатию кнопки в Vertical Layout будут добавляться другие динамические кнопочки, по нажатию на которые в QLabel будет отображаться текст с номером кнопки в следующем виде: "Button 2". На ниже следующем рисунке показан пример данного приложения, внешний вид которого не будет отличаться, тогда как реализаций программного кода будет несколько.

Вариант 1 - QSignalMapper и синтаксис на макросах

Для начала разберём вариант, который предлагается в качестве примера в официальной документации. Когда сигналы и слоты подключаются с помощью макросов, то есть вариант, который совместим с Qt 4.8.

Внешний вид приложения создавался в графическом дизайнере, поэтому не удивляйтесь использованию ui объекта.

mainwindow.h

Итак, чтобы приложение заработало, нам понадобится QSignalMapper и слот, в котором будет обрабатываться нажатие динамической кнопки. Нюанс в том, что в QLabel будет устанавливаться текст из этой самой кнопки, поэтому воспользуемся сигналом QSignalMapper::mapped(const QString &) , который будет приниматься слотом MainWindow::clicked(const QString &), в данном слоте виджет будет преобразован в объект QPushButton, и мы заберём из него текст. Текст будет предварительно устанавливаться при создании данной кнопки. Для нумерации будет использоваться счётчик созданных кнопок (переменная int counter).

mainwindow.cpp

И рассмотрим, как всё это выглядит в коде.

Вариант 2 - QSignalMapper и новый синтаксис

В первом варианте код совместим с кодом на Qt 4.8 и в целом достаточно читабелен, но что если мы не собираемся поддерживать проект на версии 4.8? Тогда первое, что нужно сделать, это переписать данный код с использованием синтаксиса на указателях и сделать небольшие вкрапление лямбда функций. И тогда вы увидите, что я подразумевал, говоря, что QSignalMapper будет выглядеть как монструозный атавизм.

mainwindow.h

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

mainwindow.cpp

Посмотрим, как теперь выглядит программный код. Казалось бы, получаем однозначный WIN:

  1. Убрали один слот, благодаря лямбда функции;
  2. Получили возможность отслеживать ошибки уже на этапе компиляции, а не в рантайме, чем грешат макросы сигналов и слотов;
  3. Привели код к стандарту Qt5.

Вариант 3 - избавляемся от QSignalMapper

А теперь избавимся от QSignalMapper. Ведь если использовать все возможности лямбда функций, то для реализации таких задач, как в данном примере, QSignalMapper вовсе не нужен.

mainwindow.h

Код в заголовочном файле немного сократился, как видите.

mainwindow.cpp

И как можете видеть, использование лямбда функции значительно сокращает код, а также избавляет в данной ситуации от использования класса QSignalMapper вовсе. Вполне возможно, что данный класс благодаря развитию самого языка C++ отомрёт вовсе.

Резюмируем .

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

Рекомендуем хостинг TIMEWEB

Рекомендуем хостинг TIMEWEB

Рекомендуемые статьи по этой тематике

По статье задано0 вопрос(ов)

Подписчики

Платёжная система
  • 26720
  • 0
  • 2
  • 0

Не можете подсказать почему?

  • 0
  • 0
  • 0
    → Александр Кузьминых
  • 28 августа 2017 г. 18:53

currentIndexChanged является сигналом с перегрузкой. Поэтому его нужно подключать через static_cast с указанием сигнатуры сигнала.

Вот такая петрушка получается:

  • 0
  • 0
  • 0
    → Евгений Легоцкой
  • 28 августа 2017 г. 20:31

Спасибо! Знал же, что сигнал с перегрузкой. Думал : "А как компилятор поймет какую именно вызывать?",- но не знал такой прием как указать сигнатуру через static_cast :)

  • 0
  • 0
  • 0
    → Александр Кузьминых
  • 28 августа 2017 г. 22:05

Этот приём в официальной документации на QComboBox указан ;-)

  • 0
  • 0
  • 0
    → Евгений Легоцкой
  • 29 августа 2017 г. 13:37

Лямбда удобная штука. Только вчера научился, мне нравится :)

Можешь сказать, когда лучше использовать слот и когда лучше лямбду.
По-моему, связывание сигнала с лямбдой нарушает принцип сигнал слотов.

А писать слот - это значит, что слот может быть вызван из вне. А это не всегда нужно. Я искал про private slots, думал, что private slot может быть связан только с сигналом своего класса, но я ошибался.

По сути лямбда ограничивает область видимости , но нарушает принцип qt сигнал-слот. Это так?

Был бы рад услышать твое мнение по этой теме :)

  • 0
  • 0
  • 0
    → Александр Кузьминых
  • 29 августа 2017 г. 13:51

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

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

В примере нужно получить сигнал от кнопки, и что-то сделать с той же самой кнопкой. Если использовать слот, то придётся держать какой-то вектор объектов в заголовочном файле, либо как сделано здесь, использовать QSignalMapper, а это опять же разрастание кода и повышение избыточности кода. А так лямбда захватывает кнопку и спокойно выполняет необходимый код. Когда кнопка будет уничтожена, а память освобождена, то лямбда автоматически будет отключена от сигнала этой кнопки и так же будет уничтожена. Так что проблем здесь никаких не возникнет.

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

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

БлогNot. QT: работаем с сигналами и слотами

QT: работаем с сигналами и слотами

Этот "классический" слегка доработанный пример на сигналы и слоты в QT показывает, как их соединять, как разрывать и возобновлять соединение. Сначала немного теории.

В QT реализована концепция функций обратного вызова (callback functions) - в результате действий пользователя вызываются обычные методы класса типа void . Чтобы сопоставить код с кнопкой, необходимо передать в функцию указатель на кнопку. Элементы графического интерфейса пользователя оказываются тесно связаны с функциональными частями программы. Для обеспечения связей сообщения и методов обработки используются макросы — карты сообщений. Примеры интерфейсов, где так сделано - Windows API, MFC.

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

Механизм сигналов и слотов основан на следующих принципах:

  • каждый класс, унаследованный от QObject , может иметь любое количество сигналов и слотов;
  • сообщения, посылаемые посредством сигналов, могут иметь множество аргументов любого типа;
  • сигнал можно соединять с различным количеством слотов. Отправляемый сигнал поступит ко всем подсоединенным слотам;
  • слот может принимать сообщения от многих сигналов, принадлежащих разным объектам;
  • соединение сигналов и слотов можно производить в любой точке приложения;
  • сигналы и слоты являются механизмами, обеспечивающими связь между объектами. Связь также может выполняться между объектами, которые находятся в различных потоках;
  • при уничтожении объекта происходит автоматическое разъединение всех сигнально-слотовых связей. Это гарантирует, что сигналы не будут отправляться к несуществующим объектам.
  • сигналы и слоты не являются частью языка C++, поэтому требуется запуск дополнительного препроцессора перед компиляцией программы;
  • отправка сигналов происходит медленнее, чем обычный вызов функции, который производится при использовании механизма функций обратного вызова;
  • существует необходимость в наследовании класса QObject ;
  • в процессе компиляции не производится никаких проверок: имеется ли сигнал или слот в соответствующих классах или нет; совместимы ли сигнал и слот друг с другом и могут ли они быть соединены вместе. Об ошибке можно будет узнать лишь тогда, когда приложение будет запущено. Вся эта информация выводится на консоль, поэтому, для того чтобы увидеть ее в Windows, в проектном файле необходимо в секции CONFIG добавить опцию console .

Сигналы (signals) - это методы, которые в состоянии осуществлять пересылку сообщений. Сигналы определяются в классе, как обычные методы, но без реализации. Они являются прототипами методов, содержащихся в заголовочном файле определения класса. Всю дальнейшую заботу о реализации кода для этих методов берет на себя препроцессор. Методы сигналов не должны возвращать каких-либо значений, поэтому перед именем метода всегда должно стоять void .

Сигнал не обязательно соединять со слотом. Если соединения не произошло, то он просто не будет обрабатываться. Подобное разделение отправляющих и получающих объектов исключает возможность того, что один из подсоединенных слотов каким-то образом сможет помешать объекту, отправившему сигналы. Библиотека предоставляет большое количество уже готовых сигналов для существующих элементов управления. В основном, для решения поставленных задач хватает этих сигналов, но иногда возникает необходимость реализации новых сигналов в своих классах.

Препроцессор обеспечит примерно такую реализацию сигнала:

Выслать сигнал можно при помощи ключевого слова emit . Ввиду того, что сигналы играют роль вызывающих методов, конструкция отправки сигнала emit doIt() приведет к обычному вызову метода doIt() . Сигналы могут отправляться из классов, которые их содержат. Например, в листинге выше сигнал doIt() может отсылаться только объектами класса MySignal , и никакими другими. Чтобы иметь возможность отослать сигнал программно из объекта этого класса, следует добавить метод sendSignal() , вызов которого заставит объект класса MySignal отправлять сигнал doIt() :

Сигналы также имеют возможность высылать информацию, передаваемую в параметре.

Обратите внимание, что в прототипе функции-сигнала не указываются имена параметров, а только типы.

Слоты (slots) — это методы, которые присоединяются к сигналам. По сути, они являются обычными методами. Основное их отличие состоит в возможности принимать сигналы. Как и обычные методы, они определяются в классе как public , private или protected . Соответственно, перед каждой группой слотов должно стоять одно из ключевых слов private slots: , protected slots: или public slots:

В слотах нельзя использовать параметры по умолчанию, например slotMethod (int n = 8) , или определять слоты как static . Классы библиотеки содержат целый ряд уже реализованных слотов. Но определение слотов для своих классов — это частая процедура.

Внутри слота вызовом метода sender() можно узнать, от какого объекта был выслан сигнал. Он возвращает указатель на объект типа QObject . Например, в этом случае на консоль будет выведено имя объекта, выславшего сигнал:

Соединение объектов осуществляется при помощи статического метода connect() , который определен в классе QObject . В общем виде, вызов метода connect() выглядит следующим образом:

  1. sender — указатель на объект, отправляющий сигнал;
  2. signal — это сигнал, с которым осуществляется соединение. Прототип (имя и аргументы) метода сигнала должен быть заключен в специальный макрос SIGNAL(method()) ;
  3. receiver — указатель на объект, который имеет слот для обработки сигнала;
  4. slot — слот, который вызывается при получении сигнала. Прототип слота должен быть заключен в специальном макросе SLOT(method()) ;
  5. type — управляет режимом обработки. Имеется три возможных значения:
    • Qt::DirectConnection — сигнал обрабатывается сразу вызовом соответствующего метода слота
    • Qt::QueuedConnection — сигнал преобразуется в событие и ставится в общую очередь для обработки
    • Qt::AutoConnection — это автоматический режим, который действует следующим образом: если отсылающий сигнал объект находится в одном потоке с принимающим его объектом, то устанавливается режим Qt::DirectConnection , в противном случае — режим Qt::QueuedConnection . Этот режим ( Qt::AutoConnection ) определен в методе connection() по умолчанию.

Как может быть осуществлено соединение объектов в программе:

Если вызов происходит из класса, унаследованного от QObject , тогда указание QObject:: можно опустить:

В случае, если слот содержится в классе, из которого производится соединение, то можно воспользоваться сокращенной формой метода connect() , опустив третий параметр ( pReceiver ), указывающий на объект-получатель. Другими словами, если в качестве объекта-получателя должен стоять указатель this , его можно просто не указывать:

Иногда возникают ситуации, когда объект не обрабатывает сигнал, а просто передает его дальше. Для этого необязательно определять слот, который в ответ на получение сигнала (при помощи emit ) отсылает свой собственный. Можно просто соединить сигналы друг с другом. Отправляемый сигнал должен содержаться в определении класса:

Отправку сигналов заблокировать можно на некоторое время, вызвав метод blockSignals() с параметром true . Объект будет "молчать", пока блокировка не будет снята тем же методом blockSignals() с параметром false . При помощи метода signalsBlocked() можно узнать текущее состояние блокировки сигналов.

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

В качестве законченного примера приведём проект Counter. Он умеет увеличивать счётчик на QLabel по нажатию кнопки "Add", а также разрывать и восстанавливать обработку сигналов по нажатию кнопки "Connect"/"Disconnect". Когда соединение отсутствует, счётчик не увеличивается. После 10 увеличений счётчика приложение в любом случае завершается.

Файл counter.h
Файл counter.cpp
Файл main.cpp

Соединять сигналы со слотами, разумеется, не обязательно программно. В режиме дизайна формы нажмите клавишу F4 для доступа к интерфейсу управления сигналами и слотами. Там же можно добавить в список новые, заданные программистом слоты.

соединение сигналов и слотов в режиме дизайна формы

соединение сигналов и слотов в режиме дизайна формы

Проиллюстрируем также "визуальное" соединение сигналов со слотами на примере обработки текстового поля QLineEdit и кнопки QPushButton , размещённых на форме виджета:

вид формы в режиме дизайна

вид формы в режиме дизайна

Нажмём в режиме дизайна формы клавишу F4 или обведённую на рисунке кнопку "Изменение сигналов/слотов", затем зажмём левую кнопку мыши на поверхности PushButton и протянем красную линию в окно виджета:

вызов настройки соединения

вызов настройки соединения

После отпускания кнопки мыши появилось окно "Настройка соединения", слева выберем сигнал clicked() , а справа нажмём кнопку Изменить, затем в новом окне Сигналы/Слоты кнопку "+" под списком слотов. К виджету добавился слот slot1() , после нажатия OK он появился в окне настройки соединения:

окно настройки соединения

окно настройки соединения

После нажатия OK связь создана и отображена на форме, вернуться к обычном виду можно нажатием клавиши F3 .

Если мы хотим просто автоматически создать пустую функцию-слот, достаточно нажать правой кнопкой мыши на PushButton и выбрать пункт меню "Перейти к слоту. ", а затем сигнал clicked() , для которого создаётся слот.

В добавленной таким способом в модуль функции можно писать код, например:

Приложение готово к работе, по нажатию кнопки выполняется этот код:

приложение в работе

приложение в работе

Существенно также то, что в пятой версии QT стало можно применять запись соединения, основанную на указателях.

Запись с макросами:

Запись на основе указателей:

Преимущество второго варианта заключается в том, что имеется возможность определить несоответствие сигнатур и неверное наименование слота или сигнала ещё на стадии компиляции проекта, а не в процессе тестирования приложения.

I'm using Qt 5.3 with MinGW 4.8.2 (due to client restrictions the Qt version cannot be upgraded). Trying to connect a QTcpSocket with a lambda expression ends up in a compiler error.

I have imported <QTcpSocket> and my class inherits QObject publicly. The Q_OBJECT macro has also been added to the header file.

This is how I am trying to connect the socket to a lambda function:

This compiles and works correctly on Qt 5.8 but not on 5.3 with MinGW 4.8.2.

I have also tried to do connect(sock, &QTcpSocket::readyRead, this, [sock]() <. >); (note I am also passing this as the third argument), but it makes no difference.

The resulting errors are:

D:\Documents\Development\X\TCPRequests.cpp:43: error: no matching function for call to 'TCPRequests::connect(QTcpSocket*&, void (QIODevice::*)(), TCPRequests::handleClient()::__lambda0)' >);

D:\Documents\Development\X\TCPRequests.cpp:43: error: template argument for 'template static typename QtPrivate::QEnableIf<((int)(QtPrivate::FunctionPointer::ArgumentCount) >= 0), QMetaObject::Connection>::Type QObject::connect(const typename QtPrivate::FunctionPointer::Object*, Func1, Func2)' uses local type 'TCPRequests::handleClient()::__lambda0' >);

D:\Documents\Development\X\TCPRequests.cpp:43: error: template argument for 'template static typename QtPrivate::QEnableIf<(QtPrivate::FunctionPointer::ArgumentCount == (-1)), QMetaObject::Connection>::Type QObject::connect(const typename QtPrivate::FunctionPointer::Object*, Func1, Func2)' uses local type 'TCPRequests::handleClient()::__lambda0' >);

Any help would be very appreciated!

Я использую Qt 5.3 с MinGW 4.8.2 (из-за ограничений клиента версия Qt не может быть обновлена). Попытка connect QTcpSocket с выражением лямбда заканчивается ошибкой компилятора.

Я импортировал <QTcpSocket> , и мой класс наследует QObject публично. Макрос Q_OBJECT также был добавлен в файл заголовка.

Это, как я пытаюсь подключить разъем к лямбда-функции:

компилируется и корректно работает на Qt 5.8, но не на 5,3 с MinGW 4.8.2.

Я также попытался сделать connect(sock, &QTcpSocket::readyRead, this, [sock]() <. >); (примечание, я также передаю в качестве третьего аргумента), но это не имеет значения.

У многих программистов, работающих с Qt4, наверняка возникало навязчивое желание соединить сигнал, посылаемый неким наследником QObject, c простой функцией, не являющейся слотом или даже членом некоторого класса. Однако если весь проект построен на объектах (как обычно и бывает), да и все они наследуются от QObject, то добавить функцию-слот куда надо не составит труда. А если нет? Если вы, например, из экономии памяти (или по другим соображениям) не хотите наследовать ваш класс от QObject, или же действие слота занимает всего 1 строчку и было бы проще и удобнее написать его в виде лямбда-выражения? Или вы по ряду причин хотите по сигналу вызывать одиночную фунцию, не являющуюся членом класса?

Столкнувшись с этой проблемой, я решил написать класс, который позволяет соединять сигнал не только с функцей-слотом, а ещё и с самой обычной функцией, а при поддержке С++11 — ещё и с лямбда-выражением.

Пишем класс SmartConnect

Для начала — что должен делать класс? Он должен наследоваться от QObject и хранить ссылку на нашу функцию. Т.е. мы связываем сигнал какого-либо класса с некоторым слотом SmartConnect, а уже SmartConnect хранит ссылку на нашу независимую функцию или лямбда-выражение, и вызывает его по своему слоту.

Самым удобным решением будет перегрузить конструктор SmartConnect — для ссылки на разные функции. Пускай он для начала работает двумя типами сигналов — которые в аргументе передают void, а также те, которые передают QString. Создадим файл smartconnect.h:

class SmartConnect : public QObject
<
Q_OBJECT
void ( * pVoidFunc ) ( void ) ;
void ( * pQStringFunc ) ( QString ) ;
public :
SmartConnect ( QObject * sender , const char * signal , void ( * pFunc ) ( void ) ) ;
SmartConnect ( QObject * sender , const char * signal , void ( * pFunc ) ( QString ) ) ;
private slots :
void voidSlot ( ) ;
void QStringSlot ( QString str ) ;
> ;

SmartConnect :: SmartConnect ( QObject * sender , const char * signal , void ( * pFunc ) ( ) ) <
pVoidFunc = pFunc ;
QObject :: connect ( sender , signal , this , SLOT ( voidSlot ( ) ) ) ;
>

SmartConnect :: SmartConnect ( QObject * sender , const char * signal , void ( * pFunc ) ( QString ) ) <
pQStringFunc = pFunc ;
QObject :: connect ( sender , signal , this , SLOT ( QStringSlot ( QString ) ) ) ;
>

void SmartConnect :: voidSlot ( ) <
pVoidFunc ( ) ;
>

void SmartConnect :: QStringSlot ( QString str ) <
pQStringFunc ( str ) ;
>

Как видите, класс действительно smart — в зависимости от вызванного конструктора сам выбирает нужный внутренний слот и соединяется с ним, а также сохраняет ссылку на нашу функцию. При желании мы можем сделать поддержку сигналов с любыми аргументами — просто добавить ссылку на функцию с этими аргументами, слот, который их принимает и конструктор. А вот внешне использовать класс будет всё также просто.

Пишем демонстрационный пример

void onClick ( ) <
qDebug ( ) << "Hello from void onClick()" ;
>

int main ( int argc , char * argv [ ] ) <
QApplication app ( argc , argv ) ;

QPushButton button1 ( "button1" ) ;
button1. show ( ) ;
SmartConnect smartConnect1 ( & button1 , SIGNAL ( clicked ( ) ) , onClick ) ;

QPushButton button2 ( "button2" ) ;
SmartConnect smartConnect2 ( & button2 , SIGNAL ( clicked ( ) ) , [ ] ( ) < qDebug ( ) << "Hello from lambda" ; >) ;
button2. show ( ) ;

Читайте также: