| |
Сигналы и слоты являются одним из фундаментальных механизмов в Qt. Он позволяет наладить обмен информацией между объектами, которые ничего не знают друг о друге. Мы уже пробовали присоединять сигналы к слотам, объявляли свои собственные сигналы и слоты, выполняли реализацию своих слотов и посылали свои сигналы. Теперь рассмотрим этот механизм поближе.
По своей природе, слоты очень близки к обычным функциям-членам в языке C++. Они могут быть виртуальными, они могут подвергаться перегрузке, они могут быть публичными, защищенными или приватными и они могут вызываться напрямую, как и обычные функции-члены. Отличие состоит в том, что слот может быть подключен к сигналу. В этом случае, функция-слот вызывается автоматически всякий раз, когда посылается сигнал.
Объявление connect() выглядит следующим образом:
connect(sender, SIGNAL(signal), receiver, SLOT(slot));где sender и receiver -- это указатели на экземпляры класса QObject (или его потомки), а signal и slot -- это сигнатуры функций. Макросы SIGNAL() и SLOT() по сути преобразуют свои аргументы в строки. В наших примерах мы до сих пор подключали к каждому из сигналов только один слот. Однако это не единственный способ.
Один сигнал может быть подключен к нескольким слотам:
connect(slider, SIGNAL(valueChanged(int)), spinBox, SLOT(setValue(int))); connect(slider, SIGNAL(valueChanged(int)), this, SLOT(updateStatusBarIndicator(int)));Когда подается сигнал, то функции-слоты вызываются одна за другой, в порядке подключения.
К одному слоту может быть подключено несколько сигналов:
connect(lcd, SIGNAL(overflow()), this, SLOT(handleMathError())); connect(calculator, SIGNAL(divisionByZero()), this, SLOT(handleMathError()));Когда посылается какой-либо из сигналов -- вызывается функция-слот.
Сигнал может быть подключен к другому сигналу:
connect(lineEdit, SIGNAL(textChanged(const QString &)), this, SIGNAL(updateRecord(const QString &)));Когда посылается первый сигнал, то вслед за ним подается и второй. С точки зрения программы, соединение типа сигнал-сигнал ничем не отличается от соединения типа сигнал-слот.
Связь между сигналом и слотом может быть разорвана:
disconnect(lcd, SIGNAL(overflow()), this, SLOT(handleMathError()));Необходимость в этом возникает довольно редко, поскольку Qt сама автоматически разрывает соединение, если один из объектов уничтожается.
connect(ftp, SIGNAL(rawCommandReply(int, const QString &)), this, SLOT(processReply(int, const QString &)));Исключение составляет случай, когда сигнал имеет большее число аргументов, чем слот. В этом случае "лишние" аргументы просто не передаются в слот.
Если типы входных аргументов не совместимы, или сигнал или слот не определены, Qt выдаст предупреждение во время исполнения. Точно так же Qt выдаст предупреждение, если в сигнатуры сигналов или слотов включены имена аргументов (в методе connect()).
Метаобъектная Система в библиотеке Qt |
---|
Одно из самых значительных достижений Qt -- это расширение возможностей языка C++ механизмом создания независимых компонентов, которые могут взаимодействовать между собой, не имея информации друг о друге. Этот механизм получил название Meta Object System и предоставляет два ключевых сервиса: сигналы-слоты и интроспекцию. Интроспекция позволяет получать метаинформацию о потомках класса QObject во время исполнения, включая список поддерживаемых сигналов, слотов и имя класса объекта. Этот механизм также реализует поддержку свойств объектов (используются в Qt Designer) и перевод текста (для нужд интернационализации). Стандарт C++ не обеспечивает возможность получения динамической метаинформации, которая необходима метаобъектной системе Qt. Поэтому данная проблема была решена созданием дополнительного инструмента moc (метаобъектный компилятор). Он собирает всю необходимую информацию из классов Q_OBJECT и делает ее доступной через вызовы обычных функций языка C++, что позволяет метаобъектной системе работать с любым компилятором C++. Механизм работает следующим образом:
Все действия выполняются автоматически, утилитами qmake и moc, так что вы довольно редко будете вспоминать об этом. Но если вас одолевает любопытство -- загляните в исходные файлы, созданные moc, и посмотрите -- что да как. |
До сих пор мы использовали сигналы и слоты исключительно с виджетами. Однако, этот механизм реализован непосредственно в классе QObject и область его применения не ограничивается графическим интерфейсом. Он может использоваться любым классом, наследником QObject:
class Employee : public QObject { Q_OBJECT public: Employee() { mySalary = 0; } int salary() const { return mySalary; } public slots: void setSalary(int newSalary); signals: void salaryChanged(int newSalary); private: int mySalary; }; void Employee::setSalary(int newSalary) { if (newSalary != mySalary) { mySalary = newSalary; emit salaryChanged(mySalary); } }
Обратите внимание на реализацию слота setSalary(). Сигнал salaryChanged() посылается только в том случае, когда newSalary != mySalary. Такой способ предотвращает попадание в бесконечный цикл при наличии обратной связи с другим объектом.
Пред. | В начало | След. |
Создание диалогов. | На уровень выше | Быстрая разработка диалогов. |
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |