Пользовательский интерфейс приложения Qt состоит из отдельных элементов управления, называемых виджетами. Это могут быть кнопки, поля ввода, полосы прокрутки, меню, и даже само окно приложения является виджетом.
При взаимодействии пользователя с приложениями виджеты могут посылать сигналы - сообщения о том, что с виджетом происходят какие-то изменения. Примеры сигналов - пользователь нажал на кнопку, или пользователь отредактировал введённое значение.
Сигналы могут быть подключены к слотам, при помощи которых можно управлять виджетами. Каждый сигнал может быть соединен с несколькими слотами, к слоту может быть подключено несколько виджетов.
У каждого слота и сигнала есть набор параметров. Например, при изменении текста в виджете QLineEdit (поле ввода) посылается сигнал, с одним параметром - строка текста (введенное значение), а изменение значения в виджете типа "полоса прокрутки" посылается сигнал, с числовым параметром. Сигналы соединяются со слотами только если у них полностью совпадают наборы параметров, то есть сигнал, передающий в качестве параметра строку, можно соединить только со слотом, принимающим в качестве параметра строку. Если есть необходимость соединить сигнал со слотом, с отличным набором параметров, нужно создать собственный класс, сделав у него промежуточный слот, который принимает сигнал с одним набором параметров, а после этого сам посылает сигнал с другим набором параметров, и соединять нужный сигнал со слотом нужно через этот "промежуточный" слот.
В программе можно создавать собственные классы, реализующие слоты и сигналы. Пример объявления класса, реализующего концепцию слотов и сигналов.
class MyClass : public QObject
{
Q_OBJECT
private:
// Объявление закрытых полей класса
public:
// Конструктор по умолчанию
MyClass(QObject *parent = 0);
signals:
// Описание сигналов, посылаемых классом
void signal1();
void signal2(int);
public slots:
// Описание слотов класса
void slot1();
void slot2(int);
};
Класс должен быть унаследован от класса QObject или производного от него класса (например, QWidget, QMainWindow и т.д.).
Сразу же после объявления класса до объявления любых полей и методов должно быть написано слово Q_OBJECT. Это директива преропроцессора, которая будет обработана при компиляции программы.
Описание сигналов должно идти после слова "signals:". Это тоже определение препроцессора. Сигналы далее определяются как функции, имеющие определенный набор параметров, и возвращающие значение типа void. Но реализовывать эти функции не нужно, это просто описание того, что класс может послать сигнал с таким названием.
А вот слоты должны быть объявлены и реализованы, как отдельные методы класса, ведь это код, который будет выполняться при подключении его к сигналу. Для описания публичных слотов используются ключевые слова "public slots".
Из метода класса (например, из слота) можно послать какой-либо объявленный ранее сигнал при помощи ключевого слова emit. Например:
emit signal1();
emit signal2(value);
Это приложение содержит виджеты QSpinBox, QSlider и QLineEdit. При изменении значения в одном из этих виджетов, изменения происходит и в других виджетах, то есть имеются некоторые общие разделяемые данные, доступные для всех виджетов.
Проблема заключается в том, что QSpinBox и QSlider при изменении значения посылают сигнал, передающий в качестве параметра int, а QLineEdit при изменении передает строку.
Поэтому соединить все эти виджеты напрямую не получится. Создадим дополнительный класс Counter, в котором будет храниться одно число (значение), и все три виджета смогут менять значение этого числа при помощи сигналов. Поэтому Counter будет содержать два слота - один принимает значения типа int (их мы соединим с сигналами виджетов QSpinBox и QSlider), а другой значение типа QString (его соединим с сигналом виджетов QLineEdit).
Но чтобы изменение значения в одном виджете отобразилось во всех остальных виджетах, сделаем так, чтобы класс Counter посылал ещё и сигналы, которые мы соединим на слоты трёх виджетов. Нам также понадобятся два типа сигналов - с числом и со строкой.
Этот файл содержит определение класса Counter, объявление поля data, в котором будет храниться число, объявление конструктора с одним параметром - указатель на родительский объект, объявление двух сигналов и двух слотов.
Этот файл содержит реализацию конструктора и двух слотов, обновляющих значение. После обновления значения, слот посылает два сигнала valueChanged с разными параметрами, для того, чтобы можно было обновить значения в связанных виджетах.
Этот файл содержит объявления трех виджетов - класса QSpinBox, QSlider, QLineEdit, а также экземпляра класса Counter. Сигналы valueChanged(int), которые посылают QSpinBox и QSlider соединяются со слотом updateValue(int) класса Counter, сигнал textChanged(QString) класса Counter соединяется со слотом updateValue(QString) класса Counter.
Наоборот, сигналы valueChanged(int) и valueChanged(const QString &) соединяются со слотами setValue(int) и setText (const QString &) соответствующих классов.