4. Основы QT — Механизм сигналов и слотов

искусственный интеллект

Сигналы и слоты — один из гордых механизмов фреймворка Qt. Так называемый сигнальный слот на самом деле является режимом наблюдателя.когда происходит событие, например, кнопка обнаруживает, что на нее нажали,он будет излучать сигнал. Эта посылка бесцельна, аналогична широковещанию.Если объект заинтересован в этом сигнале, он будет использовать функцию соединения, значение,Свяжите сигнал, который вы хотите обработать, с собственной функцией (называемой слотом) для обработки сигнала.. Это,Когда сигнал испускается, функция подключенного слота будет автоматически вызвана обратно.. Это похоже на шаблон наблюдателя: когда происходит интересующее событие, действие запускается автоматически.

4.1 Встроенные в систему сигналы и слоты

Далее доделываем небольшую функцию.Создание кнопок мы изучили выше, но функция кнопки еще не отражена.Самая большая функция кнопки - запускать некоторые вещи после нажатия.Например, когда мы нажимаем кнопку кнопка, текущее окно закроется. , то в Qt как такую ​​функцию реализовать?

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

QPushButton * quitBtn = new QPushButton("Закрыть окно",это);

  connect(quitBtn,&QPushButton::clicked,this,&MyWidget::close);

 

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

Наиболее распространенная общая форма функции connect():

connect(sender, signal, receiver, slot);

Объяснение параметра:

    1. отправитель: объект, выдавший сигнал
    2. сигнал: отправить сигнал, испускаемый объектом
    3. приемник: объект, который получает сигнал
    4. слот: функция, которую должен вызвать принимающий объект после получения сигнала (функция слота)

Итак, как вы обычно находите сигналы и слоты, которые поставляются с системой? Вам нужно использовать справочный документ. В справочном документе, таком как сигнал нажатия кнопки выше, введите QPushButton в справочном документе. Во-первых, мы можем ищем ключевые слова в Contents.signal, значение signal, но мы обнаружили, что не нашли. В это время мы должны думать, что, возможно, этот сигнал наследуется родительским классом, поэтому мы идем к его родительскому классуКлючевое слово можно найти в QAbstractButton, щелкните указатель сигналов на собственные сигналы системы, есть следующие

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

 

4.2 Пользовательские сигналы и слоты

Использование connect() позволяет нам соединять сигналы и слоты, предоставляемые системой. Однако механизм сигнальных слотов Qt не просто использует часть, предоставляемую системой, но также позволяет нам разрабатывать собственные сигналы и слоты.

Давайте посмотрим на использование сигналов и слотов Qt:

Сначала определите класс ученика и класс учителя:

Объявите сигнал в классе учителей, чтобы быть голодным

signals:

       void hungury();

Слот заявления класса студента лечить лечить

        public slots:

       void treat();

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

        void MyWidget::ClassIsOver()

{

// посылаем сигнал

    emit teacher->hungury();

}
    学生响应了槽函数,并且打印信息

//Реализация функции пользовательского слота

void Student::eat()

{

qDebug()

}

Подключите сигнальный слот в окне

    teacher = new Teacher(this);

    student = new Student(this);

 

    connect(teacher,&Teacher::hungury,student,&Student::treat);

И вызовите функцию выхода из класса, тест напечатает «пора поесть»

 

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

void hungury (имя QString); пользовательский сигнал

voidtreat(имя QString); Пользовательский слот

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

void (Teacher:: * teacherSingal)(QString) = &Teacher::hungury;

void (Student:: * studentSlot)(QString) = &Student::treat;

connect(teacher,teacherSingal,student,studentSlot);

 

 

Вопросы, требующие внимания в пользовательских слотах сигналов :

 

  1. И отправитель, и получатель должны быть подклассами QObject (конечно, за исключением случаев, когда функция слота является глобальной функцией, лямбда-выражением и т. д. без получателя);
  2. Возвращаемое значение функции сигнала и слота недействительно
  3. Сигналы нужно только декларировать, а не реализовывать
  4. Функции слота должны быть объявлены и реализованы
  5. Функция slot — это обычная функция-член, на которую будут воздействовать public, private и protected;
  6. Используйте emit для отправки сигналов в нужном месте;
  7. Используйте функцию connect() для соединения сигналов и слотов.
  8. Любая функция-член, статическая функция, глобальная функция и лямбда-выражение могут использоваться в качестве функции слота.
  9. Слоты сигналов требуют, чтобы параметры сигнала и слота были одинаковыми.Так называемая согласованность означает, что типы параметров одинаковы.
  10. Если параметры сигнала и слота несовместимы, допускается, что параметры слот-функции могут быть меньше, чем у сигнала, но при этом порядок параметров слот-функции должен быть согласован с предыдущими. сигнала. Это связано с тем, что вы можете игнорировать данные сигнала в функции слота (то есть функция слота имеет меньше параметров, чем сигнал).

4.3Расширение слота сигнала

  1. Сигнал может быть подключен к нескольким слотам

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

  1. К слоту можно подключить несколько сигналов

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

  1. Сигнал может быть подключен к другому сигналу

Когда излучается первый сигнал, излучается второй сигнал. Кроме этого, эта форма сигнал-сигнал неотличима от формы сигнал-слот.

  1. Слоты могут быть отсоединены

Это случается не часто, потому чтоКогда объект удаляется, Qt автоматически отменяет все слоты, связанные с объектом..

  1. Сигнальный слот можно отключить

использоватьdisconnectКлючевое слово может отключить слот сигнала

  1. Использование лямбда-выражений

При использовании Qt 5 все компиляторы, поддерживающие Qt 5, поддерживают лямбда-выражения.

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

4.4 Qt4версия обозначения сигнала и слота

connect(zt,SIGNAL(hungry(QString)),st,SLOT(treat(QString)));

используется здесьДва макроса, SIGNAL и SLOT, преобразуют имена двух функций в строки.. Обратите внимание, что сигнал и слот функции Connect () оба принимают строки. После того, как соединение безуспешно, QT4 не имеет ошибки компиляции (потому что все - это строка, а время компиляции не проверяет ли строковые спички), и дает ли время сочетания ошибка во время выполнения. Это, несомненно, увеличит нестабильность программы.

Qt5 синтаксически полностью совместим с Qt4, но не наоборот.

4.5 Lambdaвыражение

Лямбда-выражения в C++11Используется для определения и создания объектов анонимных функций., для упрощения программирования. Во-первых, давайте посмотрим на базовую композицию лямбда-выражения:

[capture](parameters) mutable ->return-type

{

statement

}

[Параметр объекта функции] (параметр функции перегрузки оператора) MiCable -> возвращаемое значение {функциональное тело}

 

① параметры функционального объекта;

[], идентифицируетНачало лямбда, эта часть должна существовать,нельзя опустить. Параметры объекта-функции передаются конструктору автоматически сгенерированного класса объекта-функции компилятором. Параметры объекта-функции могут использовать только локальные переменные, видимые в области видимости Lambda, когда Lambda определена (включая класс, в котором находится Lambda). Параметры функционального объекта имеют следующий вид:

    1. нулевой. Параметры функционального объекта не используются.
    2. знак равно Тело функции может использовать все видимые локальные переменные в пределах области действия Lambda (включая класс, в котором находится Lambda), ипередать значение(эквивалентно тому, что компилятор автоматически передает нам все локальные переменные по значению).
    3. &. Тело функции может использовать все видимые локальные переменные в пределах области действия Lambda (включая класс, в котором находится Lambda), ипередача по ссылке(эквивалентно тому, что компилятор автоматически передает нам все локальные переменные по ссылке).
    4. это. Тело функции может использовать переменные-члены в классе, где находится лямбда.
    5. а. Передать по значению. При передаче по значению тело функции не может модифицировать переданную копию, поскольку по умолчанию функции являются константами.Чтобы изменить копию переданного, вы можете добавить изменяемый модификатор.
    6. &а. Передать по ссылке.
    7. а, &б. Передайте a по значению и b по ссылке.
    8. =, &а, &б. Все параметры передаются по значению, кроме a и b, которые передаются по ссылке.
    9. &, а, б. За исключением a и b, которые передаются по значению, все остальные параметры передаются по ссылке.

② Параметры функции перегрузки оператора;

Идентифицирует параметр перегруженного оператора (). Если параметр отсутствует, эту часть можно опустить. Параметры могут передаваться по значению (например: (a,b)) и по ссылке (например: (&a,&b)).

③ Модифицируемые идентификаторы;

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

    QPushButton * myBtn = new QPushButton (this);

    QPushButton * myBtn2 = new QPushButton (this);

    myBtn2->move(100,100);

    int m = 10;

    connect(myBtn,&QPushButton::clicked,this,[m] ()mutable { m = 100 + 10; qDebug() << m; });

    connect(myBtn2,&QPushButton::clicked,this,[=] ()  { qDebug() << m; });

    qDebug() << m;

 

 

④ возвращаемое значение функции;

-> Тип возвращаемого значения, который идентифицирует тип возвращаемого значения функции.Когда возвращаемое значение недействительно или есть только одно место для возврата в теле функции (компилятор может автоматически определить тип возвращаемого значения), это часть можно опустить.

⑤ — тело функции;

{}, идентифицирует реализацию функции, эту часть нельзя опускать, но тело функции может быть пустым.